Version 2.18.0-193.0.dev

Merge commit 'f52068809d176b0eb78906ba3da415e94880432b' into 'dev'
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index 0284801..12d9fbb 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -44,25 +44,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('isAnalyzing');
-      try {
-        if (!obj.containsKey('isAnalyzing')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final isAnalyzing = obj['isAnalyzing'];
-        if (isAnalyzing == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (isAnalyzing is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'isAnalyzing',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type AnalyzerStatusParams');
       return false;
@@ -117,43 +100,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ClosingLabel');
       return false;
@@ -249,25 +201,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('port');
-      try {
-        if (!obj.containsKey('port')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final port = obj['port'];
-        if (port == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (port is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'port',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DartDiagnosticServer');
       return false;
@@ -354,133 +289,32 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('displayUri');
-      try {
-        if (!obj.containsKey('displayUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final displayUri = obj['displayUri'];
-        if (displayUri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (displayUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'displayUri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('file');
-      try {
-        if (!obj.containsKey('file')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final file = obj['file'];
-        if (file == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (file is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'file',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('iLength');
-      try {
-        if (!obj.containsKey('iLength')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final iLength = obj['iLength'];
-        if (iLength == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (iLength is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'iLength',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('libId');
-      try {
-        if (!obj.containsKey('libId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final libId = obj['libId'];
-        if (libId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (libId is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'libId',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('offset');
-      try {
-        if (!obj.containsKey('offset')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final offset = obj['offset'];
-        if (offset == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (offset is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'offset',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('rLength');
-      try {
-        if (!obj.containsKey('rLength')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final rLength = obj['rLength'];
-        if (rLength == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (rLength is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'rLength',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('rOffset');
-      try {
-        if (!obj.containsKey('rOffset')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final rOffset = obj['rOffset'];
-        if (rOffset == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (rOffset is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'rOffset',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DartSuggestionSetCompletionItemResolutionInfo');
@@ -584,83 +418,28 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('parameters');
-      try {
-        final parameters = obj['parameters'];
-        if (parameters != null && parameters is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'parameters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        final range = obj['range'];
-        if (range != null && !Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('returnType');
-      try {
-        final returnType = obj['returnType'];
-        if (returnType != null && returnType is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'returnType',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('typeParameters');
-      try {
-        final typeParameters = obj['typeParameters'];
-        if (typeParameters != null && typeParameters is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'typeParameters',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type Element');
       return false;
@@ -788,127 +567,40 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('attributes');
-      try {
-        final attributes = obj['attributes'];
-        if (attributes != null &&
-            (attributes is! List<Object?> ||
-                attributes.any((item) =>
-                    !FlutterOutlineAttribute.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<FlutterOutlineAttribute>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListFlutterOutlineAttribute(obj, reporter, 'attributes',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('children');
-      try {
-        final children = obj['children'];
-        if (children != null &&
-            (children is! List<Object?> ||
-                children
-                    .any((item) => !FlutterOutline.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<FlutterOutline>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListFlutterOutline(obj, reporter, 'children',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('className');
-      try {
-        final className = obj['className'];
-        if (className != null && className is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'className',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeRange');
-      try {
-        if (!obj.containsKey('codeRange')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final codeRange = obj['codeRange'];
-        if (codeRange == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(codeRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'codeRange',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dartElement');
-      try {
-        final dartElement = obj['dartElement'];
-        if (dartElement != null && !Element.canParse(dartElement, reporter)) {
-          reporter.reportError('must be of type Element');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseElement(obj, reporter, 'dartElement',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        final label = obj['label'];
-        if (label != null && label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('variableName');
-      try {
-        final variableName = obj['variableName'];
-        if (variableName != null && variableName is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'variableName',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FlutterOutline');
       return false;
@@ -993,53 +685,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('valueRange');
-      try {
-        final valueRange = obj['valueRange'];
-        if (valueRange != null && !Range.canParse(valueRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'valueRange',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FlutterOutlineAttribute');
       return false;
@@ -1124,53 +779,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('clientRequestTime');
-      try {
-        final clientRequestTime = obj['clientRequestTime'];
-        if (clientRequestTime != null && clientRequestTime is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'clientRequestTime',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('jsonrpc');
-      try {
-        if (!obj.containsKey('jsonrpc')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final jsonrpc = obj['jsonrpc'];
-        if (jsonrpc == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (jsonrpc is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'jsonrpc',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('method');
-      try {
-        if (!obj.containsKey('method')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final method = obj['method'];
-        if (method == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Method.canParse(method, reporter)) {
-          reporter.reportError('must be of type Method');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMethod(obj, reporter, 'method',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type IncomingMessage');
       return false;
@@ -1241,35 +859,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('clientRequestTime');
-      try {
-        final clientRequestTime = obj['clientRequestTime'];
-        if (clientRequestTime != null && clientRequestTime is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'clientRequestTime',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('jsonrpc');
-      try {
-        if (!obj.containsKey('jsonrpc')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final jsonrpc = obj['jsonrpc'];
-        if (jsonrpc == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (jsonrpc is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'jsonrpc',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Message');
       return false;
@@ -1348,53 +943,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('clientRequestTime');
-      try {
-        final clientRequestTime = obj['clientRequestTime'];
-        if (clientRequestTime != null && clientRequestTime is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'clientRequestTime',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('jsonrpc');
-      try {
-        if (!obj.containsKey('jsonrpc')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final jsonrpc = obj['jsonrpc'];
-        if (jsonrpc == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (jsonrpc is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'jsonrpc',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('method');
-      try {
-        if (!obj.containsKey('method')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final method = obj['method'];
-        if (method == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Method.canParse(method, reporter)) {
-          reporter.reportError('must be of type Method');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMethod(obj, reporter, 'method',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotificationMessage');
       return false;
@@ -1473,73 +1031,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('children');
-      try {
-        final children = obj['children'];
-        if (children != null &&
-            (children is! List<Object?> ||
-                children.any((item) => !Outline.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<Outline>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListOutline(obj, reporter, 'children',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeRange');
-      try {
-        if (!obj.containsKey('codeRange')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final codeRange = obj['codeRange'];
-        if (codeRange == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(codeRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'codeRange',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('element');
-      try {
-        if (!obj.containsKey('element')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final element = obj['element'];
-        if (element == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Element.canParse(element, reporter)) {
-          reporter.reportError('must be of type Element');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseElement(obj, reporter, 'element',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Outline');
       return false;
@@ -1598,25 +1103,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('packageName');
-      try {
-        if (!obj.containsKey('packageName')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final packageName = obj['packageName'];
-        if (packageName == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (packageName is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'packageName',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type PubPackageCompletionItemResolutionInfo');
@@ -1674,44 +1162,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('labels');
-      try {
-        if (!obj.containsKey('labels')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final labels = obj['labels'];
-        if (labels == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (labels is! List<Object?> ||
-            labels.any((item) => !ClosingLabel.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<ClosingLabel>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListClosingLabel(obj, reporter, 'labels',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type PublishClosingLabelsParams');
       return false;
@@ -1772,43 +1228,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('outline');
-      try {
-        if (!obj.containsKey('outline')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final outline = obj['outline'];
-        if (outline == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!FlutterOutline.canParse(outline, reporter)) {
-          reporter.reportError('must be of type FlutterOutline');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFlutterOutline(obj, reporter, 'outline',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type PublishFlutterOutlineParams');
       return false;
@@ -1867,43 +1292,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('outline');
-      try {
-        if (!obj.containsKey('outline')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final outline = obj['outline'];
-        if (outline == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Outline.canParse(outline, reporter)) {
-          reporter.reportError('must be of type Outline');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseOutline(obj, reporter, 'outline',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type PublishOutlineParams');
       return false;
@@ -1988,71 +1382,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('clientRequestTime');
-      try {
-        final clientRequestTime = obj['clientRequestTime'];
-        if (clientRequestTime != null && clientRequestTime is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'clientRequestTime',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        if (!obj.containsKey('id')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final id = obj['id'];
-        if (id == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (id is! int && id is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'id',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('jsonrpc');
-      try {
-        if (!obj.containsKey('jsonrpc')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final jsonrpc = obj['jsonrpc'];
-        if (jsonrpc == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (jsonrpc is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'jsonrpc',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('method');
-      try {
-        if (!obj.containsKey('method')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final method = obj['method'];
-        if (method == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Method.canParse(method, reporter)) {
-          reporter.reportError('must be of type Method');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMethod(obj, reporter, 'method',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type RequestMessage');
       return false;
@@ -2128,53 +1471,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('code');
-      try {
-        if (!obj.containsKey('code')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final code = obj['code'];
-        if (code == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!ErrorCodes.canParse(code, reporter)) {
-          reporter.reportError('must be of type ErrorCodes');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseErrorCodes(obj, reporter, 'code',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('data');
-      try {
-        final data = obj['data'];
-        if (data != null && data is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'data',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('message');
-      try {
-        if (!obj.containsKey('message')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final message = obj['message'];
-        if (message == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'message',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ResponseError');
       return false;
@@ -2264,59 +1570,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('clientRequestTime');
-      try {
-        final clientRequestTime = obj['clientRequestTime'];
-        if (clientRequestTime != null && clientRequestTime is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'clientRequestTime',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('error');
-      try {
-        final error = obj['error'];
-        if (error != null && !ResponseError.canParse(error, reporter)) {
-          reporter.reportError('must be of type ResponseError');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseResponseError(obj, reporter, 'error',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        if (!obj.containsKey('id')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final id = obj['id'];
-        if (id != null && id is! int && id is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'id',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('jsonrpc');
-      try {
-        if (!obj.containsKey('jsonrpc')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final jsonrpc = obj['jsonrpc'];
-        if (jsonrpc == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (jsonrpc is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'jsonrpc',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ResponseMessage');
       return false;
@@ -2395,61 +1662,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('insertTextFormat');
-      try {
-        if (!obj.containsKey('insertTextFormat')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final insertTextFormat = obj['insertTextFormat'];
-        if (insertTextFormat == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!InsertTextFormat.canParse(insertTextFormat, reporter)) {
-          reporter.reportError('must be of type InsertTextFormat');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInsertTextFormat(obj, reporter, 'insertTextFormat',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('newText');
-      try {
-        if (!obj.containsKey('newText')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final newText = obj['newText'];
-        if (newText == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (newText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'newText',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SnippetTextEdit');
       return false;
@@ -2512,35 +1734,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('message');
-      try {
-        final message = obj['message'];
-        if (message != null && message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('valid');
-      try {
-        if (!obj.containsKey('valid')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final valid = obj['valid'];
-        if (valid == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (valid is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'valid',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ValidateRefactorResult');
       return false;
@@ -2565,6 +1764,419 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+bool _canParseBool(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value is! bool) {
+      reporter.reportError('must be of type bool');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseElement(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Element.canParse(value, reporter)) {
+      reporter.reportError('must be of type Element');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseErrorCodes(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ErrorCodes.canParse(value, reporter)) {
+      reporter.reportError('must be of type ErrorCodes');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFlutterOutline(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FlutterOutline.canParse(value, reporter)) {
+      reporter.reportError('must be of type FlutterOutline');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInsertTextFormat(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InsertTextFormat.canParse(value, reporter)) {
+      reporter.reportError('must be of type InsertTextFormat');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInt(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value is! int) {
+      reporter.reportError('must be of type int');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseIntString(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && (value is! int && value is! String)) {
+      reporter.reportError('must be of type Either2<int, String>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListClosingLabel(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !ClosingLabel.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<ClosingLabel>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFlutterOutline(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !FlutterOutline.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FlutterOutline>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFlutterOutlineAttribute(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any(
+                (item) => !FlutterOutlineAttribute.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FlutterOutlineAttribute>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListOutline(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !Outline.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<Outline>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMethod(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Method.canParse(value, reporter)) {
+      reporter.reportError('must be of type Method');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseOutline(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Outline.canParse(value, reporter)) {
+      reporter.reportError('must be of type Outline');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Range.canParse(value, reporter)) {
+      reporter.reportError('must be of type Range');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseResponseError(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ResponseError.canParse(value, reporter)) {
+      reporter.reportError('must be of type ResponseError');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseString(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value is! String) {
+      reporter.reportError('must be of type String');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
 Either2<int, String> _eitherIntString(Object? value) {
   return value is int
       ? Either2.t1(value)
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 435a7cc..873841c 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -67,61 +67,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('annotationId');
-      try {
-        if (!obj.containsKey('annotationId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final annotationId = obj['annotationId'];
-        if (annotationId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (annotationId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'annotationId',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('newText');
-      try {
-        if (!obj.containsKey('newText')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final newText = obj['newText'];
-        if (newText == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (newText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'newText',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type AnnotatedTextEdit');
       return false;
@@ -189,35 +144,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('edit');
-      try {
-        if (!obj.containsKey('edit')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final edit = obj['edit'];
-        if (edit == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!WorkspaceEdit.canParse(edit, reporter)) {
-          reporter.reportError('must be of type WorkspaceEdit');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWorkspaceEdit(obj, reporter, 'edit',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        final label = obj['label'];
-        if (label != null && label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'label',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ApplyWorkspaceEditParams');
       return false;
@@ -299,45 +231,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('applied');
-      try {
-        if (!obj.containsKey('applied')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final applied = obj['applied'];
-        if (applied == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (applied is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'applied',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('failedChange');
-      try {
-        final failedChange = obj['failedChange'];
-        if (failedChange != null && failedChange is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'failedChange',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('failureReason');
-      try {
-        final failureReason = obj['failureReason'];
-        if (failureReason != null && failureReason is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'failureReason',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ApplyWorkspaceEditResult');
       return false;
@@ -435,65 +338,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('containerName');
-      try {
-        final containerName = obj['containerName'];
-        if (containerName != null && containerName is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'containerName',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SymbolKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type SymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSymbolKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type BaseSymbolInformation');
       return false;
@@ -557,17 +415,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyClientCapabilities');
       return false;
@@ -631,44 +480,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('from');
-      try {
-        if (!obj.containsKey('from')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final from = obj['from'];
-        if (from == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!CallHierarchyItem.canParse(from, reporter)) {
-          reporter.reportError('must be of type CallHierarchyItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCallHierarchyItem(obj, reporter, 'from',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('fromRanges');
-      try {
-        if (!obj.containsKey('fromRanges')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final fromRanges = obj['fromRanges'];
-        if (fromRanges == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (fromRanges is! List<Object?> ||
-            fromRanges.any((item) => !Range.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Range>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListRange(obj, reporter, 'fromRanges',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyIncomingCall');
       return false;
@@ -751,49 +568,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('item');
-      try {
-        if (!obj.containsKey('item')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final item = obj['item'];
-        if (item == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!CallHierarchyItem.canParse(item, reporter)) {
-          reporter.reportError('must be of type CallHierarchyItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCallHierarchyItem(obj, reporter, 'item',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyIncomingCallsParams');
       return false;
@@ -921,119 +705,32 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('detail');
-      try {
-        final detail = obj['detail'];
-        if (detail != null && detail is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'detail',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SymbolKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type SymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSymbolKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('selectionRange');
-      try {
-        if (!obj.containsKey('selectionRange')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final selectionRange = obj['selectionRange'];
-        if (selectionRange == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(selectionRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'selectionRange',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListSymbolTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyItem');
       return false;
@@ -1107,17 +804,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyOptions');
       return false;
@@ -1183,44 +871,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('fromRanges');
-      try {
-        if (!obj.containsKey('fromRanges')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final fromRanges = obj['fromRanges'];
-        if (fromRanges == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (fromRanges is! List<Object?> ||
-            fromRanges.any((item) => !Range.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Range>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListRange(obj, reporter, 'fromRanges',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('to');
-      try {
-        if (!obj.containsKey('to')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final to = obj['to'];
-        if (to == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!CallHierarchyItem.canParse(to, reporter)) {
-          reporter.reportError('must be of type CallHierarchyItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseCallHierarchyItem(obj, reporter, 'to',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyOutgoingCall');
       return false;
@@ -1303,49 +959,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('item');
-      try {
-        if (!obj.containsKey('item')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final item = obj['item'];
-        if (item == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!CallHierarchyItem.canParse(item, reporter)) {
-          reporter.reportError('must be of type CallHierarchyItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCallHierarchyItem(obj, reporter, 'item',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyOutgoingCallsParams');
       return false;
@@ -1428,55 +1051,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyPrepareParams');
       return false;
@@ -1566,45 +1150,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CallHierarchyRegistrationOptions');
       return false;
@@ -1664,25 +1220,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('id');
-      try {
-        if (!obj.containsKey('id')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final id = obj['id'];
-        if (id == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (id is! int && id is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'id',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CancelParams');
       return false;
@@ -1758,45 +1297,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('description');
-      try {
-        final description = obj['description'];
-        if (description != null && description is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'description',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('needsConfirmation');
-      try {
-        final needsConfirmation = obj['needsConfirmation'];
-        if (needsConfirmation != null && needsConfirmation is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'needsConfirmation',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ChangeAnnotation');
       return false;
@@ -1923,65 +1433,26 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('general');
-      try {
-        final general = obj['general'];
-        if (general != null &&
-            !GeneralClientCapabilities.canParse(general, reporter)) {
-          reporter.reportError('must be of type GeneralClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseGeneralClientCapabilities(obj, reporter, 'general',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebookDocument');
-      try {
-        final notebookDocument = obj['notebookDocument'];
-        if (notebookDocument != null &&
-            !NotebookDocumentClientCapabilities.canParse(
-                notebookDocument, reporter)) {
-          reporter.reportError(
-              'must be of type NotebookDocumentClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNotebookDocumentClientCapabilities(
+          obj, reporter, 'notebookDocument',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        final textDocument = obj['textDocument'];
-        if (textDocument != null &&
-            !TextDocumentClientCapabilities.canParse(textDocument, reporter)) {
-          reporter
-              .reportError('must be of type TextDocumentClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentClientCapabilities(
+          obj, reporter, 'textDocument',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('window');
-      try {
-        final window = obj['window'];
-        if (window != null &&
-            !WindowClientCapabilities.canParse(window, reporter)) {
-          reporter.reportError('must be of type WindowClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWindowClientCapabilities(obj, reporter, 'window',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspace');
-      try {
-        final workspace = obj['workspace'];
-        if (workspace != null &&
-            !WorkspaceClientCapabilities.canParse(workspace, reporter)) {
-          reporter.reportError('must be of type WorkspaceClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseWorkspaceClientCapabilities(obj, reporter, 'workspace',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ClientCapabilities');
       return false;
@@ -2160,89 +1631,32 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('command');
-      try {
-        final command = obj['command'];
-        if (command != null && !Command.canParse(command, reporter)) {
-          reporter.reportError('must be of type Command');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCommand(obj, reporter, 'command',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('diagnostics');
-      try {
-        final diagnostics = obj['diagnostics'];
-        if (diagnostics != null &&
-            (diagnostics is! List<Object?> ||
-                diagnostics
-                    .any((item) => !Diagnostic.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<Diagnostic>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('disabled');
-      try {
-        final disabled = obj['disabled'];
-        if (disabled != null &&
-            !CodeActionDisabled.canParse(disabled, reporter)) {
-          reporter.reportError('must be of type CodeActionDisabled');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeActionDisabled(obj, reporter, 'disabled',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('edit');
-      try {
-        final edit = obj['edit'];
-        if (edit != null && !WorkspaceEdit.canParse(edit, reporter)) {
-          reporter.reportError('must be of type WorkspaceEdit');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWorkspaceEdit(obj, reporter, 'edit',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('isPreferred');
-      try {
-        final isPreferred = obj['isPreferred'];
-        if (isPreferred != null && isPreferred is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'isPreferred',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        final kind = obj['kind'];
-        if (kind != null && !CodeActionKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type CodeActionKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeActionKind(obj, reporter, 'kind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('title');
-      try {
-        if (!obj.containsKey('title')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final title = obj['title'];
-        if (title == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (title is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'title',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeAction');
       return false;
@@ -2398,84 +1812,34 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('codeActionLiteralSupport');
-      try {
-        final codeActionLiteralSupport = obj['codeActionLiteralSupport'];
-        if (codeActionLiteralSupport != null &&
-            !CodeActionClientCapabilitiesCodeActionLiteralSupport.canParse(
-                codeActionLiteralSupport, reporter)) {
-          reporter.reportError(
-              'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeActionClientCapabilitiesCodeActionLiteralSupport(
+          obj, reporter, 'codeActionLiteralSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dataSupport');
-      try {
-        final dataSupport = obj['dataSupport'];
-        if (dataSupport != null && dataSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dataSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('disabledSupport');
-      try {
-        final disabledSupport = obj['disabledSupport'];
-        if (disabledSupport != null && disabledSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'disabledSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('honorsChangeAnnotations');
-      try {
-        final honorsChangeAnnotations = obj['honorsChangeAnnotations'];
-        if (honorsChangeAnnotations != null &&
-            honorsChangeAnnotations is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'honorsChangeAnnotations',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('isPreferredSupport');
-      try {
-        final isPreferredSupport = obj['isPreferredSupport'];
-        if (isPreferredSupport != null && isPreferredSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'isPreferredSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resolveSupport');
-      try {
-        final resolveSupport = obj['resolveSupport'];
-        if (resolveSupport != null &&
-            !CodeActionClientCapabilitiesResolveSupport.canParse(
-                resolveSupport, reporter)) {
-          reporter.reportError(
-              'must be of type CodeActionClientCapabilitiesResolveSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseCodeActionClientCapabilitiesResolveSupport(
+          obj, reporter, 'resolveSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeActionClientCapabilities');
       return false;
@@ -2542,27 +1906,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('codeActionKind');
-      try {
-        if (!obj.containsKey('codeActionKind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final codeActionKind = obj['codeActionKind'];
-        if (codeActionKind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!CodeActionLiteralSupportCodeActionKind.canParse(
-            codeActionKind, reporter)) {
-          reporter.reportError(
-              'must be of type CodeActionLiteralSupportCodeActionKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseCodeActionLiteralSupportCodeActionKind(
+          obj, reporter, 'codeActionKind',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
@@ -2617,26 +1963,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('properties');
-      try {
-        if (!obj.containsKey('properties')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final properties = obj['properties'];
-        if (properties == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (properties is! List<Object?> ||
-            properties.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'properties',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type CodeActionClientCapabilitiesResolveSupport');
@@ -2725,49 +2053,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('diagnostics');
-      try {
-        if (!obj.containsKey('diagnostics')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final diagnostics = obj['diagnostics'];
-        if (diagnostics == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (diagnostics is! List<Object?> ||
-            diagnostics.any((item) => !Diagnostic.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Diagnostic>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('only');
-      try {
-        final only = obj['only'];
-        if (only != null &&
-            (only is! List<Object?> ||
-                only.any((item) => !CodeActionKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<CodeActionKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListCodeActionKind(obj, reporter, 'only',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerKind');
-      try {
-        final triggerKind = obj['triggerKind'];
-        if (triggerKind != null &&
-            !CodeActionTriggerKind.canParse(triggerKind, reporter)) {
-          reporter.reportError('must be of type CodeActionTriggerKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseCodeActionTriggerKind(obj, reporter, 'triggerKind',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeActionContext');
       return false;
@@ -2827,25 +2122,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('reason');
-      try {
-        if (!obj.containsKey('reason')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final reason = obj['reason'];
-        if (reason == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (reason is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'reason',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeActionDisabled');
       return false;
@@ -2873,9 +2151,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// Empty kind.
   static const Empty = CodeActionKind('');
@@ -2984,26 +2260,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        if (!obj.containsKey('valueSet')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final valueSet = obj['valueSet'];
-        if (valueSet == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (valueSet is! List<Object?> ||
-            valueSet.any((item) => !CodeActionKind.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<CodeActionKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListCodeActionKind(obj, reporter, 'valueSet',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type CodeActionLiteralSupportCodeActionKind');
@@ -3089,40 +2347,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('codeActionKinds');
-      try {
-        final codeActionKinds = obj['codeActionKinds'];
-        if (codeActionKinds != null &&
-            (codeActionKinds is! List<Object?> ||
-                codeActionKinds
-                    .any((item) => !CodeActionKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<CodeActionKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListCodeActionKind(obj, reporter, 'codeActionKinds',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeActionOptions');
       return false;
@@ -3225,85 +2459,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('context');
-      try {
-        if (!obj.containsKey('context')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final context = obj['context'];
-        if (context == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!CodeActionContext.canParse(context, reporter)) {
-          reporter.reportError('must be of type CodeActionContext');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeActionContext(obj, reporter, 'context',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeActionParams');
       return false;
@@ -3410,58 +2583,21 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('codeActionKinds');
-      try {
-        final codeActionKinds = obj['codeActionKinds'];
-        if (codeActionKinds != null &&
-            (codeActionKinds is! List<Object?> ||
-                codeActionKinds
-                    .any((item) => !CodeActionKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<CodeActionKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListCodeActionKind(obj, reporter, 'codeActionKinds',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeActionRegistrationOptions');
       return false;
@@ -3504,9 +2640,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Code actions were requested automatically.
   ///
@@ -3563,25 +2697,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('href');
-      try {
-        if (!obj.containsKey('href')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final href = obj['href'];
-        if (href == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (href is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'href',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeDescription');
       return false;
@@ -3661,35 +2778,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('command');
-      try {
-        final command = obj['command'];
-        if (command != null && !Command.canParse(command, reporter)) {
-          reporter.reportError('must be of type Command');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCommand(obj, reporter, 'command',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeLens');
       return false;
@@ -3748,17 +2842,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeLensClientCapabilities');
       return false;
@@ -3823,27 +2908,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeLensOptions');
       return false;
@@ -3926,49 +2996,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeLensParams');
       return false;
@@ -4051,45 +3088,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CodeLensRegistrationOptions');
       return false;
@@ -4159,17 +3168,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('refreshSupport');
-      try {
-        final refreshSupport = obj['refreshSupport'];
-        if (refreshSupport != null && refreshSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'refreshSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type CodeLensWorkspaceClientCapabilities');
@@ -4245,79 +3245,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('alpha');
-      try {
-        if (!obj.containsKey('alpha')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final alpha = obj['alpha'];
-        if (alpha == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (alpha is! num) {
-          reporter.reportError('must be of type num');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNum(obj, reporter, 'alpha',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('blue');
-      try {
-        if (!obj.containsKey('blue')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final blue = obj['blue'];
-        if (blue == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (blue is! num) {
-          reporter.reportError('must be of type num');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNum(obj, reporter, 'blue',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('green');
-      try {
-        if (!obj.containsKey('green')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final green = obj['green'];
-        if (green == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (green is! num) {
-          reporter.reportError('must be of type num');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNum(obj, reporter, 'green',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('red');
-      try {
-        if (!obj.containsKey('red')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final red = obj['red'];
-        if (red == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (red is! num) {
-          reporter.reportError('must be of type num');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseNum(obj, reporter, 'red',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Color');
       return false;
@@ -4384,43 +3325,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('color');
-      try {
-        if (!obj.containsKey('color')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final color = obj['color'];
-        if (color == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Color.canParse(color, reporter)) {
-          reporter.reportError('must be of type Color');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseColor(obj, reporter, 'color',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ColorInformation');
       return false;
@@ -4504,48 +3414,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('additionalTextEdits');
-      try {
-        final additionalTextEdits = obj['additionalTextEdits'];
-        if (additionalTextEdits != null &&
-            (additionalTextEdits is! List<Object?> ||
-                additionalTextEdits
-                    .any((item) => !TextEdit.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<TextEdit>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextEdit(obj, reporter, 'additionalTextEdits',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textEdit');
-      try {
-        final textEdit = obj['textEdit'];
-        if (textEdit != null && !TextEdit.canParse(textEdit, reporter)) {
-          reporter.reportError('must be of type TextEdit');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextEdit(obj, reporter, 'textEdit',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ColorPresentation');
       return false;
@@ -4647,85 +3525,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('color');
-      try {
-        if (!obj.containsKey('color')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final color = obj['color'];
-        if (color == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Color.canParse(color, reporter)) {
-          reporter.reportError('must be of type Color');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseColor(obj, reporter, 'color',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ColorPresentationParams');
       return false;
@@ -4808,54 +3625,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('arguments');
-      try {
-        final arguments = obj['arguments'];
-        if (arguments != null &&
-            (arguments is! List<Object?> || arguments.any((item) => false))) {
-          reporter.reportError('must be of type List<Object?>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListObject_(obj, reporter, 'arguments',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('command');
-      try {
-        if (!obj.containsKey('command')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final command = obj['command'];
-        if (command == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (command is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'command',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('title');
-      try {
-        if (!obj.containsKey('title')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final title = obj['title'];
-        if (title == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (title is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'title',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Command');
       return false;
@@ -4981,77 +3760,31 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('completionItem');
-      try {
-        final completionItem = obj['completionItem'];
-        if (completionItem != null &&
-            !CompletionClientCapabilitiesCompletionItem.canParse(
-                completionItem, reporter)) {
-          reporter.reportError(
-              'must be of type CompletionClientCapabilitiesCompletionItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionClientCapabilitiesCompletionItem(
+          obj, reporter, 'completionItem',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('completionItemKind');
-      try {
-        final completionItemKind = obj['completionItemKind'];
-        if (completionItemKind != null &&
-            !CompletionClientCapabilitiesCompletionItemKind.canParse(
-                completionItemKind, reporter)) {
-          reporter.reportError(
-              'must be of type CompletionClientCapabilitiesCompletionItemKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionClientCapabilitiesCompletionItemKind(
+          obj, reporter, 'completionItemKind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('completionList');
-      try {
-        final completionList = obj['completionList'];
-        if (completionList != null &&
-            !CompletionClientCapabilitiesCompletionList.canParse(
-                completionList, reporter)) {
-          reporter.reportError(
-              'must be of type CompletionClientCapabilitiesCompletionList');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionClientCapabilitiesCompletionList(
+          obj, reporter, 'completionList',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('contextSupport');
-      try {
-        final contextSupport = obj['contextSupport'];
-        if (contextSupport != null && contextSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'contextSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertTextMode');
-      try {
-        final insertTextMode = obj['insertTextMode'];
-        if (insertTextMode != null &&
-            !InsertTextMode.canParse(insertTextMode, reporter)) {
-          reporter.reportError('must be of type InsertTextMode');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInsertTextMode(obj, reporter, 'insertTextMode',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionClientCapabilities');
       return false;
@@ -5243,116 +3976,46 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('commitCharactersSupport');
-      try {
-        final commitCharactersSupport = obj['commitCharactersSupport'];
-        if (commitCharactersSupport != null &&
-            commitCharactersSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'commitCharactersSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('deprecatedSupport');
-      try {
-        final deprecatedSupport = obj['deprecatedSupport'];
-        if (deprecatedSupport != null && deprecatedSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'deprecatedSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentationFormat');
-      try {
-        final documentationFormat = obj['documentationFormat'];
-        if (documentationFormat != null &&
-            (documentationFormat is! List<Object?> ||
-                documentationFormat
-                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<MarkupKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListMarkupKind(obj, reporter, 'documentationFormat',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertReplaceSupport');
-      try {
-        final insertReplaceSupport = obj['insertReplaceSupport'];
-        if (insertReplaceSupport != null && insertReplaceSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'insertReplaceSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertTextModeSupport');
-      try {
-        final insertTextModeSupport = obj['insertTextModeSupport'];
-        if (insertTextModeSupport != null &&
-            !CompletionItemInsertTextModeSupport.canParse(
-                insertTextModeSupport, reporter)) {
-          reporter.reportError(
-              'must be of type CompletionItemInsertTextModeSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionItemInsertTextModeSupport(
+          obj, reporter, 'insertTextModeSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('labelDetailsSupport');
-      try {
-        final labelDetailsSupport = obj['labelDetailsSupport'];
-        if (labelDetailsSupport != null && labelDetailsSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'labelDetailsSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('preselectSupport');
-      try {
-        final preselectSupport = obj['preselectSupport'];
-        if (preselectSupport != null && preselectSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'preselectSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resolveSupport');
-      try {
-        final resolveSupport = obj['resolveSupport'];
-        if (resolveSupport != null &&
-            !CompletionItemResolveSupport.canParse(resolveSupport, reporter)) {
-          reporter.reportError('must be of type CompletionItemResolveSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionItemResolveSupport(
+          obj, reporter, 'resolveSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('snippetSupport');
-      try {
-        final snippetSupport = obj['snippetSupport'];
-        if (snippetSupport != null && snippetSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'snippetSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tagSupport');
-      try {
-        final tagSupport = obj['tagSupport'];
-        if (tagSupport != null &&
-            !CompletionItemTagSupport.canParse(tagSupport, reporter)) {
-          reporter.reportError('must be of type CompletionItemTagSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseCompletionItemTagSupport(obj, reporter, 'tagSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type CompletionClientCapabilitiesCompletionItem');
@@ -5435,20 +4098,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        final valueSet = obj['valueSet'];
-        if (valueSet != null &&
-            (valueSet is! List<Object?> ||
-                valueSet.any(
-                    (item) => !CompletionItemKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<CompletionItemKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListCompletionItemKind(obj, reporter, 'valueSet',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type CompletionClientCapabilitiesCompletionItemKind');
@@ -5511,19 +4162,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('itemDefaults');
-      try {
-        final itemDefaults = obj['itemDefaults'];
-        if (itemDefaults != null &&
-            (itemDefaults is! List<Object?> ||
-                itemDefaults.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'itemDefaults',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type CompletionClientCapabilitiesCompletionList');
@@ -5588,35 +4228,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('triggerCharacter');
-      try {
-        final triggerCharacter = obj['triggerCharacter'];
-        if (triggerCharacter != null && triggerCharacter is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'triggerCharacter',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerKind');
-      try {
-        if (!obj.containsKey('triggerKind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final triggerKind = obj['triggerKind'];
-        if (triggerKind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!CompletionTriggerKind.canParse(triggerKind, reporter)) {
-          reporter.reportError('must be of type CompletionTriggerKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseCompletionTriggerKind(obj, reporter, 'triggerKind',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionContext');
       return false;
@@ -5950,223 +4567,80 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('additionalTextEdits');
-      try {
-        final additionalTextEdits = obj['additionalTextEdits'];
-        if (additionalTextEdits != null &&
-            (additionalTextEdits is! List<Object?> ||
-                additionalTextEdits
-                    .any((item) => !TextEdit.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<TextEdit>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextEdit(obj, reporter, 'additionalTextEdits',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('command');
-      try {
-        final command = obj['command'];
-        if (command != null && !Command.canParse(command, reporter)) {
-          reporter.reportError('must be of type Command');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCommand(obj, reporter, 'command',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('commitCharacters');
-      try {
-        final commitCharacters = obj['commitCharacters'];
-        if (commitCharacters != null &&
-            (commitCharacters is! List<Object?> ||
-                commitCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'commitCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('data');
-      try {
-        final data = obj['data'];
-        if (data != null &&
-            !CompletionItemResolutionInfo.canParse(data, reporter)) {
-          reporter.reportError('must be of type CompletionItemResolutionInfo');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionItemResolutionInfo(obj, reporter, 'data',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('deprecated');
-      try {
-        final deprecated = obj['deprecated'];
-        if (deprecated != null && deprecated is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'deprecated',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('detail');
-      try {
-        final detail = obj['detail'];
-        if (detail != null && detail is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'detail',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentation');
-      try {
-        final documentation = obj['documentation'];
-        if (documentation != null &&
-            !MarkupContent.canParse(documentation, reporter) &&
-            documentation is! String) {
-          reporter
-              .reportError('must be of type Either2<MarkupContent, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMarkupContentString(obj, reporter, 'documentation',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('filterText');
-      try {
-        final filterText = obj['filterText'];
-        if (filterText != null && filterText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'filterText',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertText');
-      try {
-        final insertText = obj['insertText'];
-        if (insertText != null && insertText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'insertText',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertTextFormat');
-      try {
-        final insertTextFormat = obj['insertTextFormat'];
-        if (insertTextFormat != null &&
-            !InsertTextFormat.canParse(insertTextFormat, reporter)) {
-          reporter.reportError('must be of type InsertTextFormat');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInsertTextFormat(obj, reporter, 'insertTextFormat',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertTextMode');
-      try {
-        final insertTextMode = obj['insertTextMode'];
-        if (insertTextMode != null &&
-            !InsertTextMode.canParse(insertTextMode, reporter)) {
-          reporter.reportError('must be of type InsertTextMode');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInsertTextMode(obj, reporter, 'insertTextMode',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        final kind = obj['kind'];
-        if (kind != null && !CompletionItemKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type CompletionItemKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionItemKind(obj, reporter, 'kind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('labelDetails');
-      try {
-        final labelDetails = obj['labelDetails'];
-        if (labelDetails != null &&
-            !CompletionItemLabelDetails.canParse(labelDetails, reporter)) {
-          reporter.reportError('must be of type CompletionItemLabelDetails');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionItemLabelDetails(obj, reporter, 'labelDetails',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('preselect');
-      try {
-        final preselect = obj['preselect'];
-        if (preselect != null && preselect is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'preselect',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('sortText');
-      try {
-        final sortText = obj['sortText'];
-        if (sortText != null && sortText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'sortText',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any(
-                    (item) => !CompletionItemTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<CompletionItemTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListCompletionItemTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textEdit');
-      try {
-        final textEdit = obj['textEdit'];
-        if (textEdit != null &&
-            !InsertReplaceEdit.canParse(textEdit, reporter) &&
-            !TextEdit.canParse(textEdit, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<InsertReplaceEdit, TextEdit>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInsertReplaceEditTextEdit(obj, reporter, 'textEdit',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textEditText');
-      try {
-        final textEditText = obj['textEditText'];
-        if (textEditText != null && textEditText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'textEditText',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionItem');
       return false;
@@ -6262,43 +4736,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('insert');
-      try {
-        if (!obj.containsKey('insert')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final insert = obj['insert'];
-        if (insert == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(insert, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'insert',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('replace');
-      try {
-        if (!obj.containsKey('replace')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final replace = obj['replace'];
-        if (replace == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(replace, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'replace',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionItemEditRange');
       return false;
@@ -6354,26 +4797,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        if (!obj.containsKey('valueSet')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final valueSet = obj['valueSet'];
-        if (valueSet == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (valueSet is! List<Object?> ||
-            valueSet.any((item) => !InsertTextMode.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<InsertTextMode>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListInsertTextMode(obj, reporter, 'valueSet',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type CompletionItemInsertTextModeSupport');
@@ -6403,10 +4828,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
-
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
   static const Class = CompletionItemKind(7);
   static const Color = CompletionItemKind(16);
   static const Constant = CompletionItemKind(21);
@@ -6496,27 +4918,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('description');
-      try {
-        final description = obj['description'];
-        if (description != null && description is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'description',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('detail');
-      try {
-        final detail = obj['detail'];
-        if (detail != null && detail is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'detail',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionItemLabelDetails');
       return false;
@@ -6572,26 +4979,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('properties');
-      try {
-        if (!obj.containsKey('properties')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final properties = obj['properties'];
-        if (properties == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (properties is! List<Object?> ||
-            properties.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'properties',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionItemResolveSupport');
       return false;
@@ -6622,9 +5011,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Render a completion as obsolete, usually using a strike-out.
   static const Deprecated = CompletionItemTag(1);
@@ -6674,27 +5061,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        if (!obj.containsKey('valueSet')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final valueSet = obj['valueSet'];
-        if (valueSet == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (valueSet is! List<Object?> ||
-            valueSet
-                .any((item) => !CompletionItemTag.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<CompletionItemTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListCompletionItemTag(obj, reporter, 'valueSet',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionItemTagSupport');
       return false;
@@ -6784,55 +5152,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('isIncomplete');
-      try {
-        if (!obj.containsKey('isIncomplete')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final isIncomplete = obj['isIncomplete'];
-        if (isIncomplete == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (isIncomplete is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'isIncomplete',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('itemDefaults');
-      try {
-        final itemDefaults = obj['itemDefaults'];
-        if (itemDefaults != null &&
-            !CompletionListItemDefaults.canParse(itemDefaults, reporter)) {
-          reporter.reportError('must be of type CompletionListItemDefaults');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionListItemDefaults(obj, reporter, 'itemDefaults',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('items');
-      try {
-        if (!obj.containsKey('items')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final items = obj['items'];
-        if (items == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (items is! List<Object?> ||
-            items.any((item) => !CompletionItem.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<CompletionItem>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListCompletionItem(obj, reporter, 'items',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionList');
       return false;
@@ -6949,54 +5278,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('commitCharacters');
-      try {
-        final commitCharacters = obj['commitCharacters'];
-        if (commitCharacters != null &&
-            (commitCharacters is! List<Object?> ||
-                commitCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'commitCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('editRange');
-      try {
-        final editRange = obj['editRange'];
-        if (editRange != null &&
-            !CompletionItemEditRange.canParse(editRange, reporter) &&
-            !Range.canParse(editRange, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<CompletionItemEditRange, Range>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionItemEditRangeRange(obj, reporter, 'editRange',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertTextFormat');
-      try {
-        final insertTextFormat = obj['insertTextFormat'];
-        if (insertTextFormat != null &&
-            !InsertTextFormat.canParse(insertTextFormat, reporter)) {
-          reporter.reportError('must be of type InsertTextFormat');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInsertTextFormat(obj, reporter, 'insertTextFormat',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertTextMode');
-      try {
-        final insertTextMode = obj['insertTextMode'];
-        if (insertTextMode != null &&
-            !InsertTextMode.canParse(insertTextMode, reporter)) {
-          reporter.reportError('must be of type InsertTextMode');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInsertTextMode(obj, reporter, 'insertTextMode',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionListItemDefaults');
       return false;
@@ -7129,64 +5424,25 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('allCommitCharacters');
-      try {
-        final allCommitCharacters = obj['allCommitCharacters'];
-        if (allCommitCharacters != null &&
-            (allCommitCharacters is! List<Object?> ||
-                allCommitCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'allCommitCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('completionItem');
-      try {
-        final completionItem = obj['completionItem'];
-        if (completionItem != null &&
-            !CompletionOptionsCompletionItem.canParse(
-                completionItem, reporter)) {
-          reporter
-              .reportError('must be of type CompletionOptionsCompletionItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionOptionsCompletionItem(
+          obj, reporter, 'completionItem',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerCharacters');
-      try {
-        final triggerCharacters = obj['triggerCharacters'];
-        if (triggerCharacters != null &&
-            (triggerCharacters is! List<Object?> ||
-                triggerCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'triggerCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionOptions');
       return false;
@@ -7254,17 +5510,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('labelDetailsSupport');
-      try {
-        final labelDetailsSupport = obj['labelDetailsSupport'];
-        if (labelDetailsSupport != null && labelDetailsSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'labelDetailsSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionOptionsCompletionItem');
       return false;
@@ -7371,77 +5618,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('context');
-      try {
-        final context = obj['context'];
-        if (context != null && !CompletionContext.canParse(context, reporter)) {
-          reporter.reportError('must be of type CompletionContext');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionContext(obj, reporter, 'context',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionParams');
       return false;
@@ -7588,82 +5782,30 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('allCommitCharacters');
-      try {
-        final allCommitCharacters = obj['allCommitCharacters'];
-        if (allCommitCharacters != null &&
-            (allCommitCharacters is! List<Object?> ||
-                allCommitCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'allCommitCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('completionItem');
-      try {
-        final completionItem = obj['completionItem'];
-        if (completionItem != null &&
-            !CompletionOptionsCompletionItem.canParse(
-                completionItem, reporter)) {
-          reporter
-              .reportError('must be of type CompletionOptionsCompletionItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionOptionsCompletionItem(
+          obj, reporter, 'completionItem',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerCharacters');
-      try {
-        final triggerCharacters = obj['triggerCharacters'];
-        if (triggerCharacters != null &&
-            (triggerCharacters is! List<Object?> ||
-                triggerCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'triggerCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CompletionRegistrationOptions');
       return false;
@@ -7785,27 +5927,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('scopeUri');
-      try {
-        final scopeUri = obj['scopeUri'];
-        if (scopeUri != null && scopeUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'scopeUri',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('section');
-      try {
-        final section = obj['section'];
-        if (section != null && section is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'section',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ConfigurationItem');
       return false;
@@ -7861,26 +5988,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('items');
-      try {
-        if (!obj.containsKey('items')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final items = obj['items'];
-        if (items == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (items is! List<Object?> ||
-            items.any((item) => !ConfigurationItem.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<ConfigurationItem>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListConfigurationItem(obj, reporter, 'items',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ConfigurationParams');
       return false;
@@ -7970,63 +6079,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('annotationId');
-      try {
-        final annotationId = obj['annotationId'];
-        if (annotationId != null && annotationId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'annotationId',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'create') {
-          reporter.reportError('must be the literal \'create\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'create')) {
+        return false;
       }
-      reporter.push('options');
-      try {
-        final options = obj['options'];
-        if (options != null && !CreateFileOptions.canParse(options, reporter)) {
-          reporter.reportError('must be of type CreateFileOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCreateFileOptions(obj, reporter, 'options',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CreateFile');
       return false;
@@ -8097,27 +6163,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('ignoreIfExists');
-      try {
-        final ignoreIfExists = obj['ignoreIfExists'];
-        if (ignoreIfExists != null && ignoreIfExists is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'ignoreIfExists',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('overwrite');
-      try {
-        final overwrite = obj['overwrite'];
-        if (overwrite != null && overwrite is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'overwrite',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type CreateFileOptions');
       return false;
@@ -8177,26 +6228,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('files');
-      try {
-        if (!obj.containsKey('files')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final files = obj['files'];
-        if (files == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (files is! List<Object?> ||
-            files.any((item) => !FileCreate.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<FileCreate>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListFileCreate(obj, reporter, 'files',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type CreateFilesParams');
       return false;
@@ -8261,27 +6294,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('linkSupport');
-      try {
-        final linkSupport = obj['linkSupport'];
-        if (linkSupport != null && linkSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'linkSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DeclarationClientCapabilities');
       return false;
@@ -8340,17 +6358,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DeclarationOptions');
       return false;
@@ -8442,67 +6451,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DeclarationParams');
       return false;
@@ -8591,45 +6553,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DeclarationRegistrationOptions');
       return false;
@@ -8704,27 +6638,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('linkSupport');
-      try {
-        final linkSupport = obj['linkSupport'];
-        if (linkSupport != null && linkSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'linkSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DefinitionClientCapabilities');
       return false;
@@ -8784,17 +6703,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DefinitionOptions');
       return false;
@@ -8887,67 +6797,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DefinitionParams');
       return false;
@@ -9021,35 +6884,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DefinitionRegistrationOptions');
       return false;
@@ -9146,63 +6987,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('annotationId');
-      try {
-        final annotationId = obj['annotationId'];
-        if (annotationId != null && annotationId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'annotationId',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'delete') {
-          reporter.reportError('must be the literal \'delete\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'delete')) {
+        return false;
       }
-      reporter.push('options');
-      try {
-        final options = obj['options'];
-        if (options != null && !DeleteFileOptions.canParse(options, reporter)) {
-          reporter.reportError('must be of type DeleteFileOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDeleteFileOptions(obj, reporter, 'options',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DeleteFile');
       return false;
@@ -9273,27 +7071,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('ignoreIfNotExists');
-      try {
-        final ignoreIfNotExists = obj['ignoreIfNotExists'];
-        if (ignoreIfNotExists != null && ignoreIfNotExists is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'ignoreIfNotExists',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('recursive');
-      try {
-        final recursive = obj['recursive'];
-        if (recursive != null && recursive is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'recursive',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DeleteFileOptions');
       return false;
@@ -9353,26 +7136,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('files');
-      try {
-        if (!obj.containsKey('files')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final files = obj['files'];
-        if (files == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (files is! List<Object?> ||
-            files.any((item) => !FileDelete.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<FileDelete>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListFileDelete(obj, reporter, 'files',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DeleteFilesParams');
       return false;
@@ -9524,111 +7289,37 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('code');
-      try {
-        final code = obj['code'];
-        if (code != null && code is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'code',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeDescription');
-      try {
-        final codeDescription = obj['codeDescription'];
-        if (codeDescription != null &&
-            !CodeDescription.canParse(codeDescription, reporter)) {
-          reporter.reportError('must be of type CodeDescription');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeDescription(obj, reporter, 'codeDescription',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('message');
-      try {
-        if (!obj.containsKey('message')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final message = obj['message'];
-        if (message == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('relatedInformation');
-      try {
-        final relatedInformation = obj['relatedInformation'];
-        if (relatedInformation != null &&
-            (relatedInformation is! List<Object?> ||
-                relatedInformation.any((item) =>
-                    !DiagnosticRelatedInformation.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<DiagnosticRelatedInformation>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDiagnosticRelatedInformation(
+          obj, reporter, 'relatedInformation',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('severity');
-      try {
-        final severity = obj['severity'];
-        if (severity != null &&
-            !DiagnosticSeverity.canParse(severity, reporter)) {
-          reporter.reportError('must be of type DiagnosticSeverity');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDiagnosticSeverity(obj, reporter, 'severity',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('source');
-      try {
-        final source = obj['source'];
-        if (source != null && source is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'source',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any((item) => !DiagnosticTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<DiagnosticTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListDiagnosticTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type Diagnostic');
       return false;
@@ -9720,27 +7411,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('relatedDocumentSupport');
-      try {
-        final relatedDocumentSupport = obj['relatedDocumentSupport'];
-        if (relatedDocumentSupport != null && relatedDocumentSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'relatedDocumentSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DiagnosticClientCapabilities');
       return false;
@@ -9831,63 +7507,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('identifier');
-      try {
-        final identifier = obj['identifier'];
-        if (identifier != null && identifier is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'identifier',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('interFileDependencies');
-      try {
-        if (!obj.containsKey('interFileDependencies')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final interFileDependencies = obj['interFileDependencies'];
-        if (interFileDependencies == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (interFileDependencies is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'interFileDependencies',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspaceDiagnostics');
-      try {
-        if (!obj.containsKey('workspaceDiagnostics')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final workspaceDiagnostics = obj['workspaceDiagnostics'];
-        if (workspaceDiagnostics == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (workspaceDiagnostics is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workspaceDiagnostics',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DiagnosticOptions');
       return false;
@@ -10012,91 +7645,29 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('identifier');
-      try {
-        final identifier = obj['identifier'];
-        if (identifier != null && identifier is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'identifier',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('interFileDependencies');
-      try {
-        if (!obj.containsKey('interFileDependencies')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final interFileDependencies = obj['interFileDependencies'];
-        if (interFileDependencies == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (interFileDependencies is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'interFileDependencies',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspaceDiagnostics');
-      try {
-        if (!obj.containsKey('workspaceDiagnostics')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final workspaceDiagnostics = obj['workspaceDiagnostics'];
-        if (workspaceDiagnostics == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (workspaceDiagnostics is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workspaceDiagnostics',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DiagnosticRegistrationOptions');
       return false;
@@ -10173,43 +7744,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('location');
-      try {
-        if (!obj.containsKey('location')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final location = obj['location'];
-        if (location == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Location.canParse(location, reporter)) {
-          reporter.reportError('must be of type Location');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLocation(obj, reporter, 'location',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('message');
-      try {
-        if (!obj.containsKey('message')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final message = obj['message'];
-        if (message == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'message',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DiagnosticRelatedInformation');
       return false;
@@ -10265,25 +7805,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('retriggerRequest');
-      try {
-        if (!obj.containsKey('retriggerRequest')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final retriggerRequest = obj['retriggerRequest'];
-        if (retriggerRequest == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (retriggerRequest is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'retriggerRequest',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DiagnosticServerCancellationData');
       return false;
@@ -10311,9 +7834,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Reports an error.
   static const Error = DiagnosticSeverity(1);
@@ -10350,9 +7871,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Deprecated or obsolete code.
   ///
@@ -10420,17 +7939,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('refreshSupport');
-      try {
-        final refreshSupport = obj['refreshSupport'];
-        if (refreshSupport != null && refreshSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'refreshSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type DiagnosticWorkspaceClientCapabilities');
@@ -10484,17 +7994,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DidChangeConfigurationClientCapabilities');
@@ -10626,45 +8127,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('change');
-      try {
-        if (!obj.containsKey('change')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final change = obj['change'];
-        if (change == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookDocumentChangeEvent.canParse(change, reporter)) {
-          reporter.reportError('must be of type NotebookDocumentChangeEvent');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNotebookDocumentChangeEvent(obj, reporter, 'change',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebookDocument');
-      try {
-        if (!obj.containsKey('notebookDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookDocument = obj['notebookDocument'];
-        if (notebookDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!VersionedNotebookDocumentIdentifier.canParse(
-            notebookDocument, reporter)) {
-          reporter.reportError(
-              'must be of type VersionedNotebookDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseVersionedNotebookDocumentIdentifier(
+          obj, reporter, 'notebookDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidChangeNotebookDocumentParams');
       return false;
@@ -10748,48 +8217,14 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('contentChanges');
-      try {
-        if (!obj.containsKey('contentChanges')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final contentChanges = obj['contentChanges'];
-        if (contentChanges == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (contentChanges is! List<Object?> ||
-            contentChanges.any((item) =>
-                !TextDocumentContentChangeEvent1.canParse(item, reporter) &&
-                !TextDocumentContentChangeEvent2.canParse(item, reporter))) {
-          reporter.reportError(
-              'must be of type List<Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
+          obj, reporter, 'contentChanges',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!VersionedTextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter
-              .reportError('must be of type VersionedTextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseVersionedTextDocumentIdentifier(
+          obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidChangeTextDocumentParams');
       return false;
@@ -10871,27 +8306,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('relativePatternSupport');
-      try {
-        final relativePatternSupport = obj['relativePatternSupport'];
-        if (relativePatternSupport != null && relativePatternSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'relativePatternSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DidChangeWatchedFilesClientCapabilities');
@@ -10949,26 +8369,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('changes');
-      try {
-        if (!obj.containsKey('changes')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final changes = obj['changes'];
-        if (changes == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (changes is! List<Object?> ||
-            changes.any((item) => !FileEvent.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<FileEvent>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListFileEvent(obj, reporter, 'changes',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidChangeWatchedFilesParams');
       return false;
@@ -11022,27 +8424,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('watchers');
-      try {
-        if (!obj.containsKey('watchers')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final watchers = obj['watchers'];
-        if (watchers == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (watchers is! List<Object?> ||
-            watchers
-                .any((item) => !FileSystemWatcher.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<FileSystemWatcher>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListFileSystemWatcher(obj, reporter, 'watchers',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DidChangeWatchedFilesRegistrationOptions');
@@ -11096,25 +8479,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('event');
-      try {
-        if (!obj.containsKey('event')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final event = obj['event'];
-        if (event == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!WorkspaceFoldersChangeEvent.canParse(event, reporter)) {
-          reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseWorkspaceFoldersChangeEvent(obj, reporter, 'event',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidChangeWorkspaceFoldersParams');
       return false;
@@ -11181,45 +8547,14 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cellTextDocuments');
-      try {
-        if (!obj.containsKey('cellTextDocuments')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final cellTextDocuments = obj['cellTextDocuments'];
-        if (cellTextDocuments == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (cellTextDocuments is! List<Object?> ||
-            cellTextDocuments.any(
-                (item) => !TextDocumentIdentifier.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<TextDocumentIdentifier>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentIdentifier(
+          obj, reporter, 'cellTextDocuments',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebookDocument');
-      try {
-        if (!obj.containsKey('notebookDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookDocument = obj['notebookDocument'];
-        if (notebookDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookDocumentIdentifier.canParse(notebookDocument, reporter)) {
-          reporter.reportError('must be of type NotebookDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseNotebookDocumentIdentifier(
+          obj, reporter, 'notebookDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidCloseNotebookDocumentParams');
       return false;
@@ -11276,25 +8611,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidCloseTextDocumentParams');
       return false;
@@ -11359,45 +8677,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cellTextDocuments');
-      try {
-        if (!obj.containsKey('cellTextDocuments')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final cellTextDocuments = obj['cellTextDocuments'];
-        if (cellTextDocuments == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (cellTextDocuments is! List<Object?> ||
-            cellTextDocuments
-                .any((item) => !TextDocumentItem.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<TextDocumentItem>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentItem(obj, reporter, 'cellTextDocuments',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebookDocument');
-      try {
-        if (!obj.containsKey('notebookDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookDocument = obj['notebookDocument'];
-        if (notebookDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookDocument.canParse(notebookDocument, reporter)) {
-          reporter.reportError('must be of type NotebookDocument');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseNotebookDocument(obj, reporter, 'notebookDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidOpenNotebookDocumentParams');
       return false;
@@ -11454,25 +8739,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentItem.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextDocumentItem(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidOpenTextDocumentParams');
       return false;
@@ -11526,25 +8794,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('notebookDocument');
-      try {
-        if (!obj.containsKey('notebookDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookDocument = obj['notebookDocument'];
-        if (notebookDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookDocumentIdentifier.canParse(notebookDocument, reporter)) {
-          reporter.reportError('must be of type NotebookDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseNotebookDocumentIdentifier(
+          obj, reporter, 'notebookDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidSaveNotebookDocumentParams');
       return false;
@@ -11607,35 +8859,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('text');
-      try {
-        final text = obj['text'];
-        if (text != null && text is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'text',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DidSaveTextDocumentParams');
       return false;
@@ -11693,17 +8922,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentColorClientCapabilities');
       return false;
@@ -11758,17 +8978,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentColorOptions');
       return false;
@@ -11847,49 +9058,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentColorParams');
       return false;
@@ -11976,45 +9154,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentColorRegistrationOptions');
       return false;
@@ -12125,69 +9275,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('identifier');
-      try {
-        final identifier = obj['identifier'];
-        if (identifier != null && identifier is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'identifier',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('previousResultId');
-      try {
-        final previousResultId = obj['previousResultId'];
-        if (previousResultId != null && previousResultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'previousResultId',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentDiagnosticParams');
       return false;
@@ -12257,32 +9362,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('relatedDocuments');
-      try {
-        if (!obj.containsKey('relatedDocuments')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final relatedDocuments = obj['relatedDocuments'];
-        if (relatedDocuments == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (relatedDocuments is! Map ||
-            (relatedDocuments.keys.any((item) =>
-                item is! String ||
-                relatedDocuments.values.any((item) =>
-                    !FullDocumentDiagnosticReport.canParse(item, reporter) &&
-                    !UnchangedDocumentDiagnosticReport.canParse(
-                        item, reporter))))) {
-          reporter.reportError(
-              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
+          obj, reporter, 'relatedDocuments',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type DocumentDiagnosticReportPartialResult');
@@ -12346,17 +9428,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type DocumentFormattingClientCapabilities');
@@ -12414,17 +9487,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentFormattingOptions');
       return false;
@@ -12497,55 +9561,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('options');
-      try {
-        if (!obj.containsKey('options')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final options = obj['options'];
-        if (options == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!FormattingOptions.canParse(options, reporter)) {
-          reporter.reportError('must be of type FormattingOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFormattingOptions(obj, reporter, 'options',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentFormattingParams');
       return false;
@@ -12621,35 +9646,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type DocumentFormattingRegistrationOptions');
@@ -12723,35 +9726,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        final kind = obj['kind'];
-        if (kind != null && !DocumentHighlightKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type DocumentHighlightKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentHighlightKind(obj, reporter, 'kind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentHighlight');
       return false;
@@ -12809,17 +9789,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type DocumentHighlightClientCapabilities');
@@ -12848,9 +9819,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Read-access of a symbol, like reading a variable.
   static const Read = DocumentHighlightKind(2);
@@ -12911,17 +9880,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentHighlightOptions');
       return false;
@@ -13014,67 +9974,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentHighlightParams');
       return false;
@@ -13152,35 +10065,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type DocumentHighlightRegistrationOptions');
@@ -13279,45 +10170,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('target');
-      try {
-        final target = obj['target'];
-        if (target != null && target is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'target',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tooltip');
-      try {
-        final tooltip = obj['tooltip'];
-        if (tooltip != null && tooltip is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'tooltip',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentLink');
       return false;
@@ -13390,27 +10252,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tooltipSupport');
-      try {
-        final tooltipSupport = obj['tooltipSupport'];
-        if (tooltipSupport != null && tooltipSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'tooltipSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentLinkClientCapabilities');
       return false;
@@ -13479,27 +10326,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentLinkOptions');
       return false;
@@ -13582,49 +10414,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentLinkParams');
       return false;
@@ -13710,45 +10509,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentLinkRegistrationOptions');
       return false;
@@ -13812,17 +10583,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DocumentOnTypeFormattingClientCapabilities');
@@ -13890,37 +10652,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('firstTriggerCharacter');
-      try {
-        if (!obj.containsKey('firstTriggerCharacter')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final firstTriggerCharacter = obj['firstTriggerCharacter'];
-        if (firstTriggerCharacter == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (firstTriggerCharacter is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'firstTriggerCharacter',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('moreTriggerCharacter');
-      try {
-        final moreTriggerCharacter = obj['moreTriggerCharacter'];
-        if (moreTriggerCharacter != null &&
-            (moreTriggerCharacter is! List<Object?> ||
-                moreTriggerCharacter.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'moreTriggerCharacter',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentOnTypeFormattingOptions');
       return false;
@@ -14007,79 +10744,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('ch');
-      try {
-        if (!obj.containsKey('ch')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final ch = obj['ch'];
-        if (ch == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (ch is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'ch',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('options');
-      try {
-        if (!obj.containsKey('options')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final options = obj['options'];
-        if (options == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!FormattingOptions.canParse(options, reporter)) {
-          reporter.reportError('must be of type FormattingOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFormattingOptions(obj, reporter, 'options',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentOnTypeFormattingParams');
       return false;
@@ -14170,55 +10848,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('firstTriggerCharacter');
-      try {
-        if (!obj.containsKey('firstTriggerCharacter')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final firstTriggerCharacter = obj['firstTriggerCharacter'];
-        if (firstTriggerCharacter == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (firstTriggerCharacter is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'firstTriggerCharacter',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('moreTriggerCharacter');
-      try {
-        final moreTriggerCharacter = obj['moreTriggerCharacter'];
-        if (moreTriggerCharacter != null &&
-            (moreTriggerCharacter is! List<Object?> ||
-                moreTriggerCharacter.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'moreTriggerCharacter',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DocumentOnTypeFormattingRegistrationOptions');
@@ -14284,17 +10924,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DocumentRangeFormattingClientCapabilities');
@@ -14353,17 +10984,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentRangeFormattingOptions');
       return false;
@@ -14445,73 +11067,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('options');
-      try {
-        if (!obj.containsKey('options')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final options = obj['options'];
-        if (options == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!FormattingOptions.canParse(options, reporter)) {
-          reporter.reportError('must be of type FormattingOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFormattingOptions(obj, reporter, 'options',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentRangeFormattingParams');
       return false;
@@ -14589,35 +11158,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DocumentRangeFormattingRegistrationOptions');
@@ -14759,124 +11306,36 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('children');
-      try {
-        final children = obj['children'];
-        if (children != null &&
-            (children is! List<Object?> ||
-                children
-                    .any((item) => !DocumentSymbol.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<DocumentSymbol>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDocumentSymbol(obj, reporter, 'children',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('deprecated');
-      try {
-        final deprecated = obj['deprecated'];
-        if (deprecated != null && deprecated is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'deprecated',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('detail');
-      try {
-        final detail = obj['detail'];
-        if (detail != null && detail is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'detail',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SymbolKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type SymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSymbolKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('selectionRange');
-      try {
-        if (!obj.containsKey('selectionRange')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final selectionRange = obj['selectionRange'];
-        if (selectionRange == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(selectionRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'selectionRange',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentSymbol');
       return false;
@@ -15003,65 +11462,26 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('hierarchicalDocumentSymbolSupport');
-      try {
-        final hierarchicalDocumentSymbolSupport =
-            obj['hierarchicalDocumentSymbolSupport'];
-        if (hierarchicalDocumentSymbolSupport != null &&
-            hierarchicalDocumentSymbolSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'hierarchicalDocumentSymbolSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('labelSupport');
-      try {
-        final labelSupport = obj['labelSupport'];
-        if (labelSupport != null && labelSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'labelSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('symbolKind');
-      try {
-        final symbolKind = obj['symbolKind'];
-        if (symbolKind != null &&
-            !DocumentSymbolClientCapabilitiesSymbolKind.canParse(
-                symbolKind, reporter)) {
-          reporter.reportError(
-              'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentSymbolClientCapabilitiesSymbolKind(
+          obj, reporter, 'symbolKind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tagSupport');
-      try {
-        final tagSupport = obj['tagSupport'];
-        if (tagSupport != null &&
-            !DocumentSymbolClientCapabilitiesTagSupport.canParse(
-                tagSupport, reporter)) {
-          reporter.reportError(
-              'must be of type DocumentSymbolClientCapabilitiesTagSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseDocumentSymbolClientCapabilitiesTagSupport(
+          obj, reporter, 'tagSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentSymbolClientCapabilities');
       return false;
@@ -15132,19 +11552,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        final valueSet = obj['valueSet'];
-        if (valueSet != null &&
-            (valueSet is! List<Object?> ||
-                valueSet.any((item) => !SymbolKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolKind(obj, reporter, 'valueSet',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
@@ -15199,26 +11608,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        if (!obj.containsKey('valueSet')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final valueSet = obj['valueSet'];
-        if (valueSet == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (valueSet is! List<Object?> ||
-            valueSet.any((item) => !SymbolTag.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolTag(obj, reporter, 'valueSet',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type DocumentSymbolClientCapabilitiesTagSupport');
@@ -15288,27 +11679,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('label');
-      try {
-        final label = obj['label'];
-        if (label != null && label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentSymbolOptions');
       return false;
@@ -15391,49 +11767,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentSymbolParams');
       return false;
@@ -15522,45 +11865,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        final label = obj['label'];
-        if (label != null && label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type DocumentSymbolRegistrationOptions');
       return false;
@@ -15598,9 +11913,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// The server detected that the content of a document got modified outside
   /// normal conditions. A server should NOT send this error code if it detects
@@ -15709,17 +12022,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ExecuteCommandClientCapabilities');
       return false;
@@ -15783,36 +12087,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('commands');
-      try {
-        if (!obj.containsKey('commands')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final commands = obj['commands'];
-        if (commands == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (commands is! List<Object?> ||
-            commands.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'commands',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ExecuteCommandOptions');
       return false;
@@ -15890,48 +12170,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('arguments');
-      try {
-        final arguments = obj['arguments'];
-        if (arguments != null &&
-            (arguments is! List<Object?> || arguments.any((item) => false))) {
-          reporter.reportError('must be of type List<Object?>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListObject_(obj, reporter, 'arguments',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('command');
-      try {
-        if (!obj.containsKey('command')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final command = obj['command'];
-        if (command == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (command is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'command',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ExecuteCommandParams');
       return false;
@@ -16001,36 +12249,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('commands');
-      try {
-        if (!obj.containsKey('commands')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final commands = obj['commands'];
-        if (commands == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (commands is! List<Object?> ||
-            commands.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'commands',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ExecuteCommandRegistrationOptions');
       return false;
@@ -16095,35 +12319,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('executionOrder');
-      try {
-        if (!obj.containsKey('executionOrder')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final executionOrder = obj['executionOrder'];
-        if (executionOrder == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (executionOrder is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'executionOrder',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('success');
-      try {
-        final success = obj['success'];
-        if (success != null && success is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'success',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ExecutionSummary');
       return false;
@@ -16205,9 +12406,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// The file got changed.
   static const Changed = FileChangeType(2);
@@ -16264,25 +12463,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileCreate');
       return false;
@@ -16335,25 +12517,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileDelete');
       return false;
@@ -16412,43 +12577,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('type');
-      try {
-        if (!obj.containsKey('type')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final type = obj['type'];
-        if (type == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!FileChangeType.canParse(type, reporter)) {
-          reporter.reportError('must be of type FileChangeType');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileChangeType(obj, reporter, 'type',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileEvent');
       return false;
@@ -16572,77 +12706,32 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('didCreate');
-      try {
-        final didCreate = obj['didCreate'];
-        if (didCreate != null && didCreate is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'didCreate',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didDelete');
-      try {
-        final didDelete = obj['didDelete'];
-        if (didDelete != null && didDelete is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'didDelete',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didRename');
-      try {
-        final didRename = obj['didRename'];
-        if (didRename != null && didRename is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'didRename',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willCreate');
-      try {
-        final willCreate = obj['willCreate'];
-        if (willCreate != null && willCreate is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'willCreate',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willDelete');
-      try {
-        final willDelete = obj['willDelete'];
-        if (willDelete != null && willDelete is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'willDelete',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willRename');
-      try {
-        final willRename = obj['willRename'];
-        if (willRename != null && willRename is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'willRename',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileOperationClientCapabilities');
       return false;
@@ -16721,35 +12810,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('pattern');
-      try {
-        if (!obj.containsKey('pattern')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final pattern = obj['pattern'];
-        if (pattern == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!FileOperationPattern.canParse(pattern, reporter)) {
-          reporter.reportError('must be of type FileOperationPattern');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationPattern(obj, reporter, 'pattern',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        final scheme = obj['scheme'];
-        if (scheme != null && scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'scheme',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileOperationFilter');
       return false;
@@ -16876,79 +12942,31 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('didCreate');
-      try {
-        final didCreate = obj['didCreate'];
-        if (didCreate != null &&
-            !FileOperationRegistrationOptions.canParse(didCreate, reporter)) {
-          reporter
-              .reportError('must be of type FileOperationRegistrationOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationRegistrationOptions(obj, reporter, 'didCreate',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didDelete');
-      try {
-        final didDelete = obj['didDelete'];
-        if (didDelete != null &&
-            !FileOperationRegistrationOptions.canParse(didDelete, reporter)) {
-          reporter
-              .reportError('must be of type FileOperationRegistrationOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationRegistrationOptions(obj, reporter, 'didDelete',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didRename');
-      try {
-        final didRename = obj['didRename'];
-        if (didRename != null &&
-            !FileOperationRegistrationOptions.canParse(didRename, reporter)) {
-          reporter
-              .reportError('must be of type FileOperationRegistrationOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationRegistrationOptions(obj, reporter, 'didRename',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willCreate');
-      try {
-        final willCreate = obj['willCreate'];
-        if (willCreate != null &&
-            !FileOperationRegistrationOptions.canParse(willCreate, reporter)) {
-          reporter
-              .reportError('must be of type FileOperationRegistrationOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationRegistrationOptions(
+          obj, reporter, 'willCreate',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willDelete');
-      try {
-        final willDelete = obj['willDelete'];
-        if (willDelete != null &&
-            !FileOperationRegistrationOptions.canParse(willDelete, reporter)) {
-          reporter
-              .reportError('must be of type FileOperationRegistrationOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationRegistrationOptions(
+          obj, reporter, 'willDelete',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willRename');
-      try {
-        final willRename = obj['willRename'];
-        if (willRename != null &&
-            !FileOperationRegistrationOptions.canParse(willRename, reporter)) {
-          reporter
-              .reportError('must be of type FileOperationRegistrationOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseFileOperationRegistrationOptions(
+          obj, reporter, 'willRename',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileOperationOptions');
       return false;
@@ -17051,47 +13069,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('glob');
-      try {
-        if (!obj.containsKey('glob')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final glob = obj['glob'];
-        if (glob == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (glob is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'glob',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('matches');
-      try {
-        final matches = obj['matches'];
-        if (matches != null &&
-            !FileOperationPatternKind.canParse(matches, reporter)) {
-          reporter.reportError('must be of type FileOperationPatternKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationPatternKind(obj, reporter, 'matches',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('options');
-      try {
-        final options = obj['options'];
-        if (options != null &&
-            !FileOperationPatternOptions.canParse(options, reporter)) {
-          reporter.reportError('must be of type FileOperationPatternOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseFileOperationPatternOptions(obj, reporter, 'options',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileOperationPattern');
       return false;
@@ -17127,9 +13114,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// The pattern matches a file only.
   static const file = FileOperationPatternKind('file');
@@ -17185,17 +13170,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('ignoreCase');
-      try {
-        final ignoreCase = obj['ignoreCase'];
-        if (ignoreCase != null && ignoreCase is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'ignoreCase',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileOperationPatternOptions');
       return false;
@@ -17251,27 +13227,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('filters');
-      try {
-        if (!obj.containsKey('filters')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final filters = obj['filters'];
-        if (filters == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (filters is! List<Object?> ||
-            filters
-                .any((item) => !FileOperationFilter.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<FileOperationFilter>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListFileOperationFilter(obj, reporter, 'filters',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileOperationRegistrationOptions');
       return false;
@@ -17333,43 +13290,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('newUri');
-      try {
-        if (!obj.containsKey('newUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final newUri = obj['newUri'];
-        if (newUri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (newUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'newUri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('oldUri');
-      try {
-        if (!obj.containsKey('oldUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final oldUri = obj['oldUri'];
-        if (oldUri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (oldUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'oldUri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileRename');
       return false;
@@ -17437,37 +13363,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('globPattern');
-      try {
-        if (!obj.containsKey('globPattern')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final globPattern = obj['globPattern'];
-        if (globPattern == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (globPattern is! String &&
-            !RelativePattern.canParse(globPattern, reporter)) {
-          reporter
-              .reportError('must be of type Either2<String, RelativePattern>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseStringRelativePattern(obj, reporter, 'globPattern',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        final kind = obj['kind'];
-        if (kind != null && !WatchKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type WatchKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseWatchKind(obj, reporter, 'kind',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FileSystemWatcher');
       return false;
@@ -17586,83 +13487,28 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('collapsedText');
-      try {
-        final collapsedText = obj['collapsedText'];
-        if (collapsedText != null && collapsedText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'collapsedText',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('endCharacter');
-      try {
-        final endCharacter = obj['endCharacter'];
-        if (endCharacter != null && endCharacter is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'endCharacter',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('endLine');
-      try {
-        if (!obj.containsKey('endLine')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final endLine = obj['endLine'];
-        if (endLine == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (endLine is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'endLine',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        final kind = obj['kind'];
-        if (kind != null && !FoldingRangeKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type FoldingRangeKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFoldingRangeKind(obj, reporter, 'kind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('startCharacter');
-      try {
-        final startCharacter = obj['startCharacter'];
-        if (startCharacter != null && startCharacter is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'startCharacter',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('startLine');
-      try {
-        if (!obj.containsKey('startLine')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final startLine = obj['startLine'];
-        if (startLine == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (startLine is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'startLine',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type FoldingRange');
       return false;
@@ -17783,63 +13629,26 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('foldingRange');
-      try {
-        final foldingRange = obj['foldingRange'];
-        if (foldingRange != null &&
-            !FoldingRangeClientCapabilitiesFoldingRange.canParse(
-                foldingRange, reporter)) {
-          reporter.reportError(
-              'must be of type FoldingRangeClientCapabilitiesFoldingRange');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFoldingRangeClientCapabilitiesFoldingRange(
+          obj, reporter, 'foldingRange',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('foldingRangeKind');
-      try {
-        final foldingRangeKind = obj['foldingRangeKind'];
-        if (foldingRangeKind != null &&
-            !FoldingRangeClientCapabilitiesFoldingRangeKind.canParse(
-                foldingRangeKind, reporter)) {
-          reporter.reportError(
-              'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFoldingRangeClientCapabilitiesFoldingRangeKind(
+          obj, reporter, 'foldingRangeKind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('lineFoldingOnly');
-      try {
-        final lineFoldingOnly = obj['lineFoldingOnly'];
-        if (lineFoldingOnly != null && lineFoldingOnly is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'lineFoldingOnly',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('rangeLimit');
-      try {
-        final rangeLimit = obj['rangeLimit'];
-        if (rangeLimit != null && rangeLimit is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'rangeLimit',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FoldingRangeClientCapabilities');
       return false;
@@ -17905,17 +13714,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('collapsedText');
-      try {
-        final collapsedText = obj['collapsedText'];
-        if (collapsedText != null && collapsedText is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'collapsedText',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type FoldingRangeClientCapabilitiesFoldingRange');
@@ -17973,20 +13773,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        final valueSet = obj['valueSet'];
-        if (valueSet != null &&
-            (valueSet is! List<Object?> ||
-                valueSet.any(
-                    (item) => !FoldingRangeKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<FoldingRangeKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListFoldingRangeKind(obj, reporter, 'valueSet',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
@@ -18016,9 +13804,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// Folding range for a comment
   static const Comment = FoldingRangeKind('comment');
@@ -18077,17 +13863,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FoldingRangeOptions');
       return false;
@@ -18166,49 +13943,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FoldingRangeParams');
       return false;
@@ -18295,45 +14039,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FoldingRangeRegistrationOptions');
       return false;
@@ -18438,73 +14154,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('insertFinalNewline');
-      try {
-        final insertFinalNewline = obj['insertFinalNewline'];
-        if (insertFinalNewline != null && insertFinalNewline is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'insertFinalNewline',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('insertSpaces');
-      try {
-        if (!obj.containsKey('insertSpaces')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final insertSpaces = obj['insertSpaces'];
-        if (insertSpaces == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (insertSpaces is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'insertSpaces',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tabSize');
-      try {
-        if (!obj.containsKey('tabSize')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final tabSize = obj['tabSize'];
-        if (tabSize == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (tabSize is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'tabSize',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('trimFinalNewlines');
-      try {
-        final trimFinalNewlines = obj['trimFinalNewlines'];
-        if (trimFinalNewlines != null && trimFinalNewlines is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'trimFinalNewlines',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('trimTrailingWhitespace');
-      try {
-        final trimTrailingWhitespace = obj['trimTrailingWhitespace'];
-        if (trimTrailingWhitespace != null && trimTrailingWhitespace is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'trimTrailingWhitespace',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FormattingOptions');
       return false;
@@ -18600,54 +14267,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('items');
-      try {
-        if (!obj.containsKey('items')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final items = obj['items'];
-        if (items == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (items is! List<Object?> ||
-            items.any((item) => !Diagnostic.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Diagnostic>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDiagnostic(obj, reporter, 'items',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'full') {
-          reporter.reportError('must be the literal \'full\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'full')) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        final resultId = obj['resultId'];
-        if (resultId != null && resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'resultId',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type FullDocumentDiagnosticReport');
       return false;
@@ -18773,57 +14402,22 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('markdown');
-      try {
-        final markdown = obj['markdown'];
-        if (markdown != null &&
-            !MarkdownClientCapabilities.canParse(markdown, reporter)) {
-          reporter.reportError('must be of type MarkdownClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMarkdownClientCapabilities(obj, reporter, 'markdown',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('positionEncodings');
-      try {
-        final positionEncodings = obj['positionEncodings'];
-        if (positionEncodings != null &&
-            (positionEncodings is! List<Object?> ||
-                positionEncodings.any((item) =>
-                    !PositionEncodingKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<PositionEncodingKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListPositionEncodingKind(obj, reporter, 'positionEncodings',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('regularExpressions');
-      try {
-        final regularExpressions = obj['regularExpressions'];
-        if (regularExpressions != null &&
-            !RegularExpressionsClientCapabilities.canParse(
-                regularExpressions, reporter)) {
-          reporter.reportError(
-              'must be of type RegularExpressionsClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRegularExpressionsClientCapabilities(
+          obj, reporter, 'regularExpressions',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('staleRequestSupport');
-      try {
-        final staleRequestSupport = obj['staleRequestSupport'];
-        if (staleRequestSupport != null &&
-            !GeneralClientCapabilitiesStaleRequestSupport.canParse(
-                staleRequestSupport, reporter)) {
-          reporter.reportError(
-              'must be of type GeneralClientCapabilitiesStaleRequestSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseGeneralClientCapabilitiesStaleRequestSupport(
+          obj, reporter, 'staleRequestSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type GeneralClientCapabilities');
       return false;
@@ -18894,44 +14488,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cancel');
-      try {
-        if (!obj.containsKey('cancel')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final cancel = obj['cancel'];
-        if (cancel == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (cancel is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'cancel',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('retryOnContentModified');
-      try {
-        if (!obj.containsKey('retryOnContentModified')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final retryOnContentModified = obj['retryOnContentModified'];
-        if (retryOnContentModified == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (retryOnContentModified is! List<Object?> ||
-            retryOnContentModified.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'retryOnContentModified',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type GeneralClientCapabilitiesStaleRequestSupport');
@@ -19001,37 +14563,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('contents');
-      try {
-        if (!obj.containsKey('contents')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final contents = obj['contents'];
-        if (contents == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!MarkupContent.canParse(contents, reporter) &&
-            contents is! String) {
-          reporter
-              .reportError('must be of type Either2<MarkupContent, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMarkupContentString(obj, reporter, 'contents',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        final range = obj['range'];
-        if (range != null && !Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type Hover');
       return false;
@@ -19101,30 +14638,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('contentFormat');
-      try {
-        final contentFormat = obj['contentFormat'];
-        if (contentFormat != null &&
-            (contentFormat is! List<Object?> ||
-                contentFormat
-                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<MarkupKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListMarkupKind(obj, reporter, 'contentFormat',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type HoverClientCapabilities');
       return false;
@@ -19185,17 +14704,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type HoverOptions');
       return false;
@@ -19270,55 +14780,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type HoverParams');
       return false;
@@ -19390,35 +14861,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type HoverRegistrationOptions');
       return false;
@@ -19493,27 +14942,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('linkSupport');
-      try {
-        final linkSupport = obj['linkSupport'];
-        if (linkSupport != null && linkSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'linkSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ImplementationClientCapabilities');
       return false;
@@ -19572,17 +15006,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ImplementationOptions');
       return false;
@@ -19674,67 +15099,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ImplementationParams');
       return false;
@@ -19823,45 +15201,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ImplementationRegistrationOptions');
       return false;
@@ -20042,124 +15392,42 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('capabilities');
-      try {
-        if (!obj.containsKey('capabilities')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final capabilities = obj['capabilities'];
-        if (capabilities == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!ClientCapabilities.canParse(capabilities, reporter)) {
-          reporter.reportError('must be of type ClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseClientCapabilities(obj, reporter, 'capabilities',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('clientInfo');
-      try {
-        final clientInfo = obj['clientInfo'];
-        if (clientInfo != null &&
-            !InitializeParamsClientInfo.canParse(clientInfo, reporter)) {
-          reporter.reportError('must be of type InitializeParamsClientInfo');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInitializeParamsClientInfo(obj, reporter, 'clientInfo',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('locale');
-      try {
-        final locale = obj['locale'];
-        if (locale != null && locale is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'locale',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('processId');
-      try {
-        if (!obj.containsKey('processId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final processId = obj['processId'];
-        if (processId != null && processId is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'processId',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('rootPath');
-      try {
-        final rootPath = obj['rootPath'];
-        if (rootPath != null && rootPath is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'rootPath',
+          allowsUndefined: true, allowsNull: true)) {
+        return false;
       }
-      reporter.push('rootUri');
-      try {
-        if (!obj.containsKey('rootUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final rootUri = obj['rootUri'];
-        if (rootUri != null && rootUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'rootUri',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('trace');
-      try {
-        final trace = obj['trace'];
-        if (trace != null &&
-            trace != 'off' &&
-            trace != 'messages' &&
-            trace != 'compact' &&
-            trace != 'verbose') {
-          reporter.reportError(
-              'must be one of the literals \'off\', \'messages\', \'compact\', \'verbose\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteralUnion(obj, reporter, 'trace',
+          allowsUndefined: true,
+          allowsNull: false,
+          literals: {'off', 'messages', 'compact', 'verbose'})) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspaceFolders');
-      try {
-        final workspaceFolders = obj['workspaceFolders'];
-        if (workspaceFolders != null &&
-            (workspaceFolders is! List<Object?> ||
-                workspaceFolders.any(
-                    (item) => !WorkspaceFolder.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<WorkspaceFolder>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListWorkspaceFolder(obj, reporter, 'workspaceFolders',
+          allowsUndefined: true, allowsNull: true);
     } else {
       reporter.reportError('must be of type InitializeParams');
       return false;
@@ -20240,35 +15508,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        final version = obj['version'];
-        if (version != null && version is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'version',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InitializeParamsClientInfo');
       return false;
@@ -20339,36 +15584,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('capabilities');
-      try {
-        if (!obj.containsKey('capabilities')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final capabilities = obj['capabilities'];
-        if (capabilities == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!ServerCapabilities.canParse(capabilities, reporter)) {
-          reporter.reportError('must be of type ServerCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseServerCapabilities(obj, reporter, 'capabilities',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('serverInfo');
-      try {
-        final serverInfo = obj['serverInfo'];
-        if (serverInfo != null &&
-            !InitializeResultServerInfo.canParse(serverInfo, reporter)) {
-          reporter.reportError('must be of type InitializeResultServerInfo');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInitializeResultServerInfo(obj, reporter, 'serverInfo',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InitializeResult');
       return false;
@@ -20432,35 +15653,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        final version = obj['version'];
-        if (version != null && version is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'version',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InitializeResultServerInfo');
       return false;
@@ -20545,7 +15743,7 @@
     final kind =
         kindJson != null ? InlayHintKind.fromJson(kindJson as int) : null;
     final labelJson = json['label'];
-    final label = _eitherListString(labelJson);
+    final label = _eitherListInlayHintLabelPartString(labelJson);
     final paddingLeftJson = json['paddingLeft'];
     final paddingLeft = paddingLeftJson as bool?;
     final paddingRightJson = json['paddingRight'];
@@ -20640,101 +15838,32 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        final kind = obj['kind'];
-        if (kind != null && !InlayHintKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type InlayHintKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInlayHintKind(obj, reporter, 'kind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! List<Object?> ||
-            label.any((item) => !InlayHintLabelPart.canParse(item, reporter)) &&
-                label is! String) {
-          reporter.reportError(
-              'must be of type Either2<List<InlayHintLabelPart>, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('paddingLeft');
-      try {
-        final paddingLeft = obj['paddingLeft'];
-        if (paddingLeft != null && paddingLeft is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'paddingLeft',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('paddingRight');
-      try {
-        final paddingRight = obj['paddingRight'];
-        if (paddingRight != null && paddingRight is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'paddingRight',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textEdits');
-      try {
-        final textEdits = obj['textEdits'];
-        if (textEdits != null &&
-            (textEdits is! List<Object?> ||
-                textEdits.any((item) => !TextEdit.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<TextEdit>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextEdit(obj, reporter, 'textEdits',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tooltip');
-      try {
-        final tooltip = obj['tooltip'];
-        if (tooltip != null &&
-            !MarkupContent.canParse(tooltip, reporter) &&
-            tooltip is! String) {
-          reporter
-              .reportError('must be of type Either2<MarkupContent, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMarkupContentString(obj, reporter, 'tooltip',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlayHint');
       return false;
@@ -20819,30 +15948,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resolveSupport');
-      try {
-        final resolveSupport = obj['resolveSupport'];
-        if (resolveSupport != null &&
-            !InlayHintClientCapabilitiesResolveSupport.canParse(
-                resolveSupport, reporter)) {
-          reporter.reportError(
-              'must be of type InlayHintClientCapabilitiesResolveSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInlayHintClientCapabilitiesResolveSupport(
+          obj, reporter, 'resolveSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlayHintClientCapabilities');
       return false;
@@ -20899,26 +16011,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('properties');
-      try {
-        if (!obj.containsKey('properties')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final properties = obj['properties'];
-        if (properties == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (properties is! List<Object?> ||
-            properties.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'properties',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type InlayHintClientCapabilitiesResolveSupport');
@@ -20949,9 +16043,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// An inlay hint that is for a parameter.
   static const Parameter = InlayHintKind(2);
@@ -21055,58 +16147,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('command');
-      try {
-        final command = obj['command'];
-        if (command != null && !Command.canParse(command, reporter)) {
-          reporter.reportError('must be of type Command');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCommand(obj, reporter, 'command',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('location');
-      try {
-        final location = obj['location'];
-        if (location != null && !Location.canParse(location, reporter)) {
-          reporter.reportError('must be of type Location');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLocation(obj, reporter, 'location',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tooltip');
-      try {
-        final tooltip = obj['tooltip'];
-        if (tooltip != null &&
-            !MarkupContent.canParse(tooltip, reporter) &&
-            tooltip is! String) {
-          reporter
-              .reportError('must be of type Either2<MarkupContent, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMarkupContentString(obj, reporter, 'tooltip',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('value');
-      try {
-        if (!obj.containsKey('value')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final value = obj['value'];
-        if (value == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (value is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'value',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlayHintLabelPart');
       return false;
@@ -21182,27 +16236,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlayHintOptions');
       return false;
@@ -21280,55 +16319,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlayHintParams');
       return false;
@@ -21430,55 +16430,21 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlayHintRegistrationOptions');
       return false;
@@ -21552,17 +16518,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('refreshSupport');
-      try {
-        final refreshSupport = obj['refreshSupport'];
-        if (refreshSupport != null && refreshSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'refreshSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type InlayHintWorkspaceClientCapabilities');
@@ -21619,17 +16576,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueClientCapabilities');
       return false;
@@ -21690,43 +16638,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('frameId');
-      try {
-        if (!obj.containsKey('frameId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final frameId = obj['frameId'];
-        if (frameId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (frameId is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'frameId',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('stoppedLocation');
-      try {
-        if (!obj.containsKey('stoppedLocation')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final stoppedLocation = obj['stoppedLocation'];
-        if (stoppedLocation == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(stoppedLocation, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'stoppedLocation',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueContext');
       return false;
@@ -21796,35 +16713,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('expression');
-      try {
-        final expression = obj['expression'];
-        if (expression != null && expression is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'expression',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueEvaluatableExpression');
       return false;
@@ -21886,17 +16780,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueOptions');
       return false;
@@ -21980,73 +16865,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('context');
-      try {
-        if (!obj.containsKey('context')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final context = obj['context'];
-        if (context == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!InlineValueContext.canParse(context, reporter)) {
-          reporter.reportError('must be of type InlineValueContext');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInlineValueContext(obj, reporter, 'context',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueParams');
       return false;
@@ -22138,45 +16970,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueRegistrationOptions');
       return false;
@@ -22247,43 +17051,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('text');
-      try {
-        if (!obj.containsKey('text')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final text = obj['text'];
-        if (text == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (text is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'text',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueText');
       return false;
@@ -22361,53 +17134,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('caseSensitiveLookup');
-      try {
-        if (!obj.containsKey('caseSensitiveLookup')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final caseSensitiveLookup = obj['caseSensitiveLookup'];
-        if (caseSensitiveLookup == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (caseSensitiveLookup is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'caseSensitiveLookup',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('variableName');
-      try {
-        final variableName = obj['variableName'];
-        if (variableName != null && variableName is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'variableName',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type InlineValueVariableLookup');
       return false;
@@ -22475,17 +17211,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('refreshSupport');
-      try {
-        final refreshSupport = obj['refreshSupport'];
-        if (refreshSupport != null && refreshSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'refreshSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type InlineValueWorkspaceClientCapabilities');
@@ -22555,61 +17282,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('insert');
-      try {
-        if (!obj.containsKey('insert')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final insert = obj['insert'];
-        if (insert == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(insert, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'insert',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('newText');
-      try {
-        if (!obj.containsKey('newText')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final newText = obj['newText'];
-        if (newText == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (newText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'newText',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('replace');
-      try {
-        if (!obj.containsKey('replace')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final replace = obj['replace'];
-        if (replace == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(replace, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'replace',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type InsertReplaceEdit');
       return false;
@@ -22690,9 +17372,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// The editor adjusts leading whitespace of new lines so that they match the
   /// indentation up to the cursor of the line for which the item is accepted.
@@ -22760,17 +17440,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type LinkedEditingRangeClientCapabilities');
@@ -22827,17 +17498,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type LinkedEditingRangeOptions');
       return false;
@@ -22911,55 +17573,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type LinkedEditingRangeParams');
       return false;
@@ -23047,45 +17670,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type LinkedEditingRangeRegistrationOptions');
@@ -23165,36 +17760,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('ranges');
-      try {
-        if (!obj.containsKey('ranges')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final ranges = obj['ranges'];
-        if (ranges == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (ranges is! List<Object?> ||
-            ranges.any((item) => !Range.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Range>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListRange(obj, reporter, 'ranges',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('wordPattern');
-      try {
-        final wordPattern = obj['wordPattern'];
-        if (wordPattern != null && wordPattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'wordPattern',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type LinkedEditingRanges');
       return false;
@@ -23254,43 +17825,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Location');
       return false;
@@ -23384,72 +17924,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('originSelectionRange');
-      try {
-        final originSelectionRange = obj['originSelectionRange'];
-        if (originSelectionRange != null &&
-            !Range.canParse(originSelectionRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'originSelectionRange',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('targetRange');
-      try {
-        if (!obj.containsKey('targetRange')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final targetRange = obj['targetRange'];
-        if (targetRange == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(targetRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'targetRange',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('targetSelectionRange');
-      try {
-        if (!obj.containsKey('targetSelectionRange')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final targetSelectionRange = obj['targetSelectionRange'];
-        if (targetSelectionRange == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(targetSelectionRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'targetSelectionRange',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('targetUri');
-      try {
-        if (!obj.containsKey('targetUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final targetUri = obj['targetUri'];
-        if (targetUri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (targetUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'targetUri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type LocationLink');
       return false;
@@ -23516,43 +18004,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('message');
-      try {
-        if (!obj.containsKey('message')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final message = obj['message'];
-        if (message == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('type');
-      try {
-        if (!obj.containsKey('type')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final type = obj['type'];
-        if (type == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!MessageType.canParse(type, reporter)) {
-          reporter.reportError('must be of type MessageType');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMessageType(obj, reporter, 'type',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type LogMessageParams');
       return false;
@@ -23613,35 +18070,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('message');
-      try {
-        if (!obj.containsKey('message')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final message = obj['message'];
-        if (message == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('verbose');
-      try {
-        final verbose = obj['verbose'];
-        if (verbose != null && verbose is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'verbose',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type LogTraceParams');
       return false;
@@ -23722,47 +18156,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('allowedTags');
-      try {
-        final allowedTags = obj['allowedTags'];
-        if (allowedTags != null &&
-            (allowedTags is! List<Object?> ||
-                allowedTags.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'allowedTags',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('parser');
-      try {
-        if (!obj.containsKey('parser')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final parser = obj['parser'];
-        if (parser == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (parser is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'parser',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        final version = obj['version'];
-        if (version != null && version is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'version',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type MarkdownClientCapabilities');
       return false;
@@ -23851,43 +18254,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!MarkupKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type MarkupKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMarkupKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('value');
-      try {
-        if (!obj.containsKey('value')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final value = obj['value'];
-        if (value == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (value is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'value',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type MarkupContent');
       return false;
@@ -23981,25 +18353,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('title');
-      try {
-        if (!obj.containsKey('title')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final title = obj['title'];
-        if (title == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (title is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'title',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type MessageActionItem');
       return false;
@@ -24027,9 +18382,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// An error message.
   static const Error = MessageType(1);
@@ -24064,9 +18417,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// Constant for the 'callHierarchy/incomingCalls' method.
   static const callHierarchy_incomingCalls =
@@ -24445,71 +18796,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('identifier');
-      try {
-        if (!obj.containsKey('identifier')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final identifier = obj['identifier'];
-        if (identifier == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (identifier is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'identifier',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        final kind = obj['kind'];
-        if (kind != null && !MonikerKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type MonikerKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMonikerKind(obj, reporter, 'kind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        if (!obj.containsKey('scheme')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final scheme = obj['scheme'];
-        if (scheme == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'scheme',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('unique');
-      try {
-        if (!obj.containsKey('unique')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final unique = obj['unique'];
-        if (unique == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!UniquenessLevel.canParse(unique, reporter)) {
-          reporter.reportError('must be of type UniquenessLevel');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseUniquenessLevel(obj, reporter, 'unique',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Moniker');
       return false;
@@ -24574,17 +18874,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type MonikerClientCapabilities');
       return false;
@@ -24614,9 +18905,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// The moniker represents a symbol that is exported from a project
   static const export = MonikerKind('export');
@@ -24676,17 +18965,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type MonikerOptions');
       return false;
@@ -24778,67 +19058,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type MonikerParams');
       return false;
@@ -24911,35 +19144,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type MonikerRegistrationOptions');
       return false;
@@ -25037,54 +19248,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('document');
-      try {
-        if (!obj.containsKey('document')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final document = obj['document'];
-        if (document == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (document is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'document',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('executionSummary');
-      try {
-        final executionSummary = obj['executionSummary'];
-        if (executionSummary != null &&
-            !ExecutionSummary.canParse(executionSummary, reporter)) {
-          reporter.reportError('must be of type ExecutionSummary');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseExecutionSummary(obj, reporter, 'executionSummary',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookCellKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type NotebookCellKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseNotebookCellKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookCell');
       return false;
@@ -25165,55 +19338,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cells');
-      try {
-        final cells = obj['cells'];
-        if (cells != null &&
-            (cells is! List<Object?> ||
-                cells.any((item) => !NotebookCell.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<NotebookCell>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListNotebookCell(obj, reporter, 'cells',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('deleteCount');
-      try {
-        if (!obj.containsKey('deleteCount')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final deleteCount = obj['deleteCount'];
-        if (deleteCount == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (deleteCount is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'deleteCount',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('start');
-      try {
-        if (!obj.containsKey('start')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final start = obj['start'];
-        if (start == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (start is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'start',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookCellArrayChange');
       return false;
@@ -25250,9 +19384,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// A code-cell is source code.
   static const Code = NotebookCellKind(2);
@@ -25327,39 +19459,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('language');
-      try {
-        final language = obj['language'];
-        if (language != null && language is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'language',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebook');
-      try {
-        if (!obj.containsKey('notebook')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebook = obj['notebook'];
-        if (notebook == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookDocumentFilter1.canParse(notebook, reporter) &&
-            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
-            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
-            notebook is! String) {
-          reporter.reportError(
-              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseEither3String(obj, reporter, 'notebook',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookCellTextDocumentFilter');
       return false;
@@ -25455,80 +19560,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cells');
-      try {
-        if (!obj.containsKey('cells')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final cells = obj['cells'];
-        if (cells == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (cells is! List<Object?> ||
-            cells.any((item) => !NotebookCell.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<NotebookCell>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListNotebookCell(obj, reporter, 'cells',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebookType');
-      try {
-        if (!obj.containsKey('notebookType')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookType = obj['notebookType'];
-        if (notebookType == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (notebookType is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'notebookType',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        if (!obj.containsKey('version')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final version = obj['version'];
-        if (version == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocument');
       return false;
@@ -25609,19 +19654,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cells');
-      try {
-        final cells = obj['cells'];
-        if (cells != null &&
-            !NotebookDocumentChangeEventCells.canParse(cells, reporter)) {
-          reporter
-              .reportError('must be of type NotebookDocumentChangeEventCells');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseNotebookDocumentChangeEventCells(obj, reporter, 'cells',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocumentChangeEvent');
       return false;
@@ -25707,47 +19741,18 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('data');
-      try {
-        final data = obj['data'];
-        if (data != null &&
-            (data is! List<Object?> ||
-                data.any((item) => !NotebookCell.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<NotebookCell>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListNotebookCell(obj, reporter, 'data',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('structure');
-      try {
-        final structure = obj['structure'];
-        if (structure != null &&
-            !NotebookDocumentChangeEventCellsStructure.canParse(
-                structure, reporter)) {
-          reporter.reportError(
-              'must be of type NotebookDocumentChangeEventCellsStructure');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNotebookDocumentChangeEventCellsStructure(
+          obj, reporter, 'structure',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textContent');
-      try {
-        final textContent = obj['textContent'];
-        if (textContent != null &&
-            (textContent is! List<Object?> ||
-                textContent.any((item) =>
-                    !NotebookDocumentChangeEventCellsTextContent.canParse(
-                        item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<NotebookDocumentChangeEventCellsTextContent>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListNotebookDocumentChangeEventCellsTextContent(
+          obj, reporter, 'textContent',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocumentChangeEventCells');
       return false;
@@ -25836,51 +19841,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('array');
-      try {
-        if (!obj.containsKey('array')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final array = obj['array'];
-        if (array == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookCellArrayChange.canParse(array, reporter)) {
-          reporter.reportError('must be of type NotebookCellArrayChange');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNotebookCellArrayChange(obj, reporter, 'array',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didClose');
-      try {
-        final didClose = obj['didClose'];
-        if (didClose != null &&
-            (didClose is! List<Object?> ||
-                didClose.any((item) =>
-                    !TextDocumentIdentifier.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<TextDocumentIdentifier>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentIdentifier(obj, reporter, 'didClose',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didOpen');
-      try {
-        final didOpen = obj['didOpen'];
-        if (didOpen != null &&
-            (didOpen is! List<Object?> ||
-                didOpen.any(
-                    (item) => !TextDocumentItem.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<TextDocumentItem>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListTextDocumentItem(obj, reporter, 'didOpen',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentChangeEventCellsStructure');
@@ -25952,48 +19922,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('changes');
-      try {
-        if (!obj.containsKey('changes')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final changes = obj['changes'];
-        if (changes == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (changes is! List<Object?> ||
-            changes.any((item) =>
-                !TextDocumentContentChangeEvent1.canParse(item, reporter) &&
-                !TextDocumentContentChangeEvent2.canParse(item, reporter))) {
-          reporter.reportError(
-              'must be of type List<Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
+          obj, reporter, 'changes',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('document');
-      try {
-        if (!obj.containsKey('document')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final document = obj['document'];
-        if (document == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!VersionedTextDocumentIdentifier.canParse(document, reporter)) {
-          reporter
-              .reportError('must be of type VersionedTextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseVersionedTextDocumentIdentifier(obj, reporter, 'document',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentChangeEventCellsTextContent');
@@ -26064,27 +19999,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('synchronization');
-      try {
-        if (!obj.containsKey('synchronization')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final synchronization = obj['synchronization'];
-        if (synchronization == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookDocumentSyncClientCapabilities.canParse(
-            synchronization, reporter)) {
-          reporter.reportError(
-              'must be of type NotebookDocumentSyncClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseNotebookDocumentSyncClientCapabilities(
+          obj, reporter, 'synchronization',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type NotebookDocumentClientCapabilities');
@@ -26155,45 +20072,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('notebookType');
-      try {
-        if (!obj.containsKey('notebookType')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookType = obj['notebookType'];
-        if (notebookType == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (notebookType is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'notebookType',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('pattern');
-      try {
-        final pattern = obj['pattern'];
-        if (pattern != null && pattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'pattern',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        final scheme = obj['scheme'];
-        if (scheme != null && scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'scheme',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocumentFilter1');
       return false;
@@ -26269,45 +20157,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('notebookType');
-      try {
-        final notebookType = obj['notebookType'];
-        if (notebookType != null && notebookType is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'notebookType',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('pattern');
-      try {
-        final pattern = obj['pattern'];
-        if (pattern != null && pattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'pattern',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        if (!obj.containsKey('scheme')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final scheme = obj['scheme'];
-        if (scheme == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'scheme',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocumentFilter2');
       return false;
@@ -26383,45 +20242,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('notebookType');
-      try {
-        final notebookType = obj['notebookType'];
-        if (notebookType != null && notebookType is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'notebookType',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('pattern');
-      try {
-        if (!obj.containsKey('pattern')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final pattern = obj['pattern'];
-        if (pattern == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (pattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'pattern',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        final scheme = obj['scheme'];
-        if (scheme != null && scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'scheme',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocumentFilter3');
       return false;
@@ -26480,25 +20310,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocumentIdentifier');
       return false;
@@ -26567,28 +20380,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('executionSummarySupport');
-      try {
-        final executionSummarySupport = obj['executionSummarySupport'];
-        if (executionSummarySupport != null &&
-            executionSummarySupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'executionSummarySupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentSyncClientCapabilities');
@@ -26674,41 +20471,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('notebookSelector');
-      try {
-        if (!obj.containsKey('notebookSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookSelector = obj['notebookSelector'];
-        if (notebookSelector == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (notebookSelector is! List<Object?> ||
-            notebookSelector.any((item) =>
-                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
-                    item, reporter) &&
-                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
-                    item, reporter))) {
-          reporter.reportError(
-              'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
+          obj, reporter, 'notebookSelector',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('save');
-      try {
-        final save = obj['save'];
-        if (save != null && save is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'save',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type NotebookDocumentSyncOptions');
       return false;
@@ -26792,44 +20561,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cells');
-      try {
-        final cells = obj['cells'];
-        if (cells != null &&
-            (cells is! List<Object?> ||
-                cells.any((item) =>
-                    !NotebookDocumentSyncOptionsNotebookSelectorCells.canParse(
-                        item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<NotebookDocumentSyncOptionsNotebookSelectorCells>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelectorCells(
+          obj, reporter, 'cells',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebook');
-      try {
-        if (!obj.containsKey('notebook')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebook = obj['notebook'];
-        if (notebook == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!NotebookDocumentFilter1.canParse(notebook, reporter) &&
-            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
-            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
-            notebook is! String) {
-          reporter.reportError(
-              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseEither3String(obj, reporter, 'notebook',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentSyncOptionsNotebookSelector');
@@ -26911,44 +20649,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cells');
-      try {
-        if (!obj.containsKey('cells')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final cells = obj['cells'];
-        if (cells == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (cells is! List<Object?> ||
-            cells.any((item) =>
-                !NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse(
-                    item, reporter))) {
-          reporter.reportError(
-              'must be of type List<NotebookDocumentSyncOptionsNotebookSelector2Cells>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelector2Cells(
+          obj, reporter, 'cells',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebook');
-      try {
-        final notebook = obj['notebook'];
-        if (notebook != null &&
-            !NotebookDocumentFilter1.canParse(notebook, reporter) &&
-            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
-            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
-            notebook is! String) {
-          reporter.reportError(
-              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseEither3String(obj, reporter, 'notebook',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentSyncOptionsNotebookSelector2');
@@ -27008,25 +20715,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('language');
-      try {
-        if (!obj.containsKey('language')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final language = obj['language'];
-        if (language == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (language is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'language',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentSyncOptionsNotebookSelector2Cells');
@@ -27078,25 +20768,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('language');
-      try {
-        if (!obj.containsKey('language')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final language = obj['language'];
-        if (language == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (language is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'language',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentSyncOptionsNotebookSelectorCells');
@@ -27186,51 +20859,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebookSelector');
-      try {
-        if (!obj.containsKey('notebookSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final notebookSelector = obj['notebookSelector'];
-        if (notebookSelector == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (notebookSelector is! List<Object?> ||
-            notebookSelector.any((item) =>
-                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
-                    item, reporter) &&
-                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
-                    item, reporter))) {
-          reporter.reportError(
-              'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
+          obj, reporter, 'notebookSelector',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('save');
-      try {
-        final save = obj['save'];
-        if (save != null && save is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'save',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type NotebookDocumentSyncRegistrationOptions');
@@ -27314,39 +20953,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        if (!obj.containsKey('version')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final version = obj['version'];
-        if (version != null && version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: false, allowsNull: true);
     } else {
       reporter.reportError(
           'must be of type OptionalVersionedTextDocumentIdentifier');
@@ -27425,38 +21037,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentation');
-      try {
-        final documentation = obj['documentation'];
-        if (documentation != null &&
-            !MarkupContent.canParse(documentation, reporter) &&
-            documentation is! String) {
-          reporter
-              .reportError('must be of type Either2<MarkupContent, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMarkupContentString(obj, reporter, 'documentation',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ParameterInformation');
       return false;
@@ -27593,19 +21179,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type PartialResultParams');
       return false;
@@ -27660,43 +21235,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('placeholder');
-      try {
-        if (!obj.containsKey('placeholder')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final placeholder = obj['placeholder'];
-        if (placeholder == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (placeholder is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'placeholder',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type PlaceholderAndRange');
       return false;
@@ -27794,43 +21338,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('character');
-      try {
-        if (!obj.containsKey('character')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final character = obj['character'];
-        if (character == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (character is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'character',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('line');
-      try {
-        if (!obj.containsKey('line')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final line = obj['line'];
-        if (line == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (line is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'line',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Position');
       return false;
@@ -27864,9 +21377,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// Character offsets count UTF-16 code units.
   ///
@@ -27950,55 +21461,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type PrepareRenameParams');
       return false;
@@ -28053,25 +21525,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('defaultBehavior');
-      try {
-        if (!obj.containsKey('defaultBehavior')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final defaultBehavior = obj['defaultBehavior'];
-        if (defaultBehavior == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (defaultBehavior is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'defaultBehavior',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type PrepareRenameResult2');
       return false;
@@ -28098,9 +21553,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// The client's default behavior is to select the identifier according the to
   /// language's syntax rule.
@@ -28160,43 +21613,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('value');
-      try {
-        if (!obj.containsKey('value')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final value = obj['value'];
-        if (value == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (value is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'value',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type PreviousResultId');
       return false;
@@ -28258,25 +21680,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('token');
-      try {
-        if (!obj.containsKey('token')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final token = obj['token'];
-        if (token == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (token is! int && token is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'token',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ProgressParams');
       return false;
@@ -28389,60 +21794,25 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('codeDescriptionSupport');
-      try {
-        final codeDescriptionSupport = obj['codeDescriptionSupport'];
-        if (codeDescriptionSupport != null && codeDescriptionSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'codeDescriptionSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dataSupport');
-      try {
-        final dataSupport = obj['dataSupport'];
-        if (dataSupport != null && dataSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dataSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('relatedInformation');
-      try {
-        final relatedInformation = obj['relatedInformation'];
-        if (relatedInformation != null && relatedInformation is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'relatedInformation',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tagSupport');
-      try {
-        final tagSupport = obj['tagSupport'];
-        if (tagSupport != null &&
-            !PublishDiagnosticsClientCapabilitiesTagSupport.canParse(
-                tagSupport, reporter)) {
-          reporter.reportError(
-              'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePublishDiagnosticsClientCapabilitiesTagSupport(
+          obj, reporter, 'tagSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('versionSupport');
-      try {
-        final versionSupport = obj['versionSupport'];
-        if (versionSupport != null && versionSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'versionSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type PublishDiagnosticsClientCapabilities');
@@ -28506,26 +21876,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        if (!obj.containsKey('valueSet')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final valueSet = obj['valueSet'];
-        if (valueSet == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (valueSet is! List<Object?> ||
-            valueSet.any((item) => !DiagnosticTag.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<DiagnosticTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListDiagnosticTag(obj, reporter, 'valueSet',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
@@ -28601,54 +21953,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('diagnostics');
-      try {
-        if (!obj.containsKey('diagnostics')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final diagnostics = obj['diagnostics'];
-        if (diagnostics == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (diagnostics is! List<Object?> ||
-            diagnostics.any((item) => !Diagnostic.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Diagnostic>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        final version = obj['version'];
-        if (version != null && version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type PublishDiagnosticsParams');
       return false;
@@ -28725,43 +22039,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('end');
-      try {
-        if (!obj.containsKey('end')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final end = obj['end'];
-        if (end == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(end, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'end',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('start');
-      try {
-        if (!obj.containsKey('start')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final start = obj['start'];
-        if (start == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(start, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParsePosition(obj, reporter, 'start',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Range');
       return false;
@@ -28818,17 +22101,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ReferenceClientCapabilities');
       return false;
@@ -28880,25 +22154,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('includeDeclaration');
-      try {
-        if (!obj.containsKey('includeDeclaration')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final includeDeclaration = obj['includeDeclaration'];
-        if (includeDeclaration == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (includeDeclaration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'includeDeclaration',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ReferenceContext');
       return false;
@@ -28954,17 +22211,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ReferenceOptions');
       return false;
@@ -29065,85 +22313,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('context');
-      try {
-        if (!obj.containsKey('context')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final context = obj['context'];
-        if (context == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!ReferenceContext.canParse(context, reporter)) {
-          reporter.reportError('must be of type ReferenceContext');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseReferenceContext(obj, reporter, 'context',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ReferenceParams');
       return false;
@@ -29219,35 +22406,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ReferenceRegistrationOptions');
       return false;
@@ -29326,43 +22491,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('id');
-      try {
-        if (!obj.containsKey('id')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final id = obj['id'];
-        if (id == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('method');
-      try {
-        if (!obj.containsKey('method')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final method = obj['method'];
-        if (method == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (method is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'method',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Registration');
       return false;
@@ -29420,27 +22554,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('registrations');
-      try {
-        if (!obj.containsKey('registrations')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final registrations = obj['registrations'];
-        if (registrations == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (registrations is! List<Object?> ||
-            registrations
-                .any((item) => !Registration.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Registration>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListRegistration(obj, reporter, 'registrations',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type RegistrationParams');
       return false;
@@ -29505,35 +22620,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('engine');
-      try {
-        if (!obj.containsKey('engine')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final engine = obj['engine'];
-        if (engine == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (engine is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'engine',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        final version = obj['version'];
-        if (version != null && version is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'version',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type RegularExpressionsClientCapabilities');
@@ -29644,73 +22736,21 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('items');
-      try {
-        if (!obj.containsKey('items')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final items = obj['items'];
-        if (items == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (items is! List<Object?> ||
-            items.any((item) => !Diagnostic.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Diagnostic>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDiagnostic(obj, reporter, 'items',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'full') {
-          reporter.reportError('must be the literal \'full\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'full')) {
+        return false;
       }
-      reporter.push('relatedDocuments');
-      try {
-        final relatedDocuments = obj['relatedDocuments'];
-        if (relatedDocuments != null &&
-            (relatedDocuments is! Map ||
-                (relatedDocuments.keys.any((item) =>
-                    item is! String ||
-                    relatedDocuments.values.any((item) =>
-                        !FullDocumentDiagnosticReport.canParse(
-                            item, reporter) &&
-                        !UnchangedDocumentDiagnosticReport.canParse(
-                            item, reporter)))))) {
-          reporter.reportError(
-              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
+          obj, reporter, 'relatedDocuments',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        final resultId = obj['resultId'];
-        if (resultId != null && resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'resultId',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type RelatedFullDocumentDiagnosticReport');
@@ -29822,62 +22862,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'unchanged') {
-          reporter.reportError('must be the literal \'unchanged\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'unchanged')) {
+        return false;
       }
-      reporter.push('relatedDocuments');
-      try {
-        final relatedDocuments = obj['relatedDocuments'];
-        if (relatedDocuments != null &&
-            (relatedDocuments is! Map ||
-                (relatedDocuments.keys.any((item) =>
-                    item is! String ||
-                    relatedDocuments.values.any((item) =>
-                        !FullDocumentDiagnosticReport.canParse(
-                            item, reporter) &&
-                        !UnchangedDocumentDiagnosticReport.canParse(
-                            item, reporter)))))) {
-          reporter.reportError(
-              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
+          obj, reporter, 'relatedDocuments',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        if (!obj.containsKey('resultId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final resultId = obj['resultId'];
-        if (resultId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'resultId',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type RelatedUnchangedDocumentDiagnosticReport');
@@ -29957,45 +22952,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('baseUri');
-      try {
-        if (!obj.containsKey('baseUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final baseUri = obj['baseUri'];
-        if (baseUri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (baseUri is! String &&
-            !WorkspaceFolder.canParse(baseUri, reporter)) {
-          reporter
-              .reportError('must be of type Either2<String, WorkspaceFolder>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseStringWorkspaceFolder(obj, reporter, 'baseUri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('pattern');
-      try {
-        if (!obj.containsKey('pattern')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final pattern = obj['pattern'];
-        if (pattern == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (pattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'pattern',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type RelativePattern');
       return false;
@@ -30099,51 +23061,21 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('honorsChangeAnnotations');
-      try {
-        final honorsChangeAnnotations = obj['honorsChangeAnnotations'];
-        if (honorsChangeAnnotations != null &&
-            honorsChangeAnnotations is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'honorsChangeAnnotations',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('prepareSupport');
-      try {
-        final prepareSupport = obj['prepareSupport'];
-        if (prepareSupport != null && prepareSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'prepareSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('prepareSupportDefaultBehavior');
-      try {
-        final prepareSupportDefaultBehavior =
-            obj['prepareSupportDefaultBehavior'];
-        if (prepareSupportDefaultBehavior != null &&
-            !PrepareSupportDefaultBehavior.canParse(
-                prepareSupportDefaultBehavior, reporter)) {
-          reporter.reportError('must be of type PrepareSupportDefaultBehavior');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParsePrepareSupportDefaultBehavior(
+          obj, reporter, 'prepareSupportDefaultBehavior',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type RenameClientCapabilities');
       return false;
@@ -30248,81 +23180,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('annotationId');
-      try {
-        final annotationId = obj['annotationId'];
-        if (annotationId != null && annotationId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'annotationId',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'rename') {
-          reporter.reportError('must be the literal \'rename\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'rename')) {
+        return false;
       }
-      reporter.push('newUri');
-      try {
-        if (!obj.containsKey('newUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final newUri = obj['newUri'];
-        if (newUri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (newUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'newUri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('oldUri');
-      try {
-        if (!obj.containsKey('oldUri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final oldUri = obj['oldUri'];
-        if (oldUri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (oldUri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'oldUri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('options');
-      try {
-        final options = obj['options'];
-        if (options != null && !RenameFileOptions.canParse(options, reporter)) {
-          reporter.reportError('must be of type RenameFileOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRenameFileOptions(obj, reporter, 'options',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type RenameFile');
       return false;
@@ -30395,27 +23270,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('ignoreIfExists');
-      try {
-        final ignoreIfExists = obj['ignoreIfExists'];
-        if (ignoreIfExists != null && ignoreIfExists is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'ignoreIfExists',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('overwrite');
-      try {
-        final overwrite = obj['overwrite'];
-        if (overwrite != null && overwrite is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'overwrite',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type RenameFileOptions');
       return false;
@@ -30476,26 +23336,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('files');
-      try {
-        if (!obj.containsKey('files')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final files = obj['files'];
-        if (files == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (files is! List<Object?> ||
-            files.any((item) => !FileRename.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<FileRename>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListFileRename(obj, reporter, 'files',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type RenameFilesParams');
       return false;
@@ -30562,27 +23404,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('prepareProvider');
-      try {
-        final prepareProvider = obj['prepareProvider'];
-        if (prepareProvider != null && prepareProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'prepareProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type RenameOptions');
       return false;
@@ -30667,73 +23494,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('newName');
-      try {
-        if (!obj.containsKey('newName')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final newName = obj['newName'];
-        if (newName == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (newName is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'newName',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type RenameParams');
       return false;
@@ -30820,45 +23594,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('prepareProvider');
-      try {
-        final prepareProvider = obj['prepareProvider'];
-        if (prepareProvider != null && prepareProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'prepareProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type RenameRegistrationOptions');
       return false;
@@ -30940,35 +23686,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('annotationId');
-      try {
-        final annotationId = obj['annotationId'];
-        if (annotationId != null && annotationId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'annotationId',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ResourceOperation');
       return false;
@@ -31068,17 +23791,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('includeText');
-      try {
-        final includeText = obj['includeText'];
-        if (includeText != null && includeText is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'includeText',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SaveOptions');
       return false;
@@ -31143,35 +23857,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('parent');
-      try {
-        final parent = obj['parent'];
-        if (parent != null && !SelectionRange.canParse(parent, reporter)) {
-          reporter.reportError('must be of type SelectionRange');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSelectionRange(obj, reporter, 'parent',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SelectionRange');
       return false;
@@ -31230,17 +23921,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SelectionRangeClientCapabilities');
       return false;
@@ -31295,17 +23977,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SelectionRangeOptions');
       return false;
@@ -31394,68 +24067,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('positions');
-      try {
-        if (!obj.containsKey('positions')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final positions = obj['positions'];
-        if (positions == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (positions is! List<Object?> ||
-            positions.any((item) => !Position.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Position>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListPosition(obj, reporter, 'positions',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SelectionRangeParams');
       return false;
@@ -31545,45 +24170,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SelectionRangeRegistrationOptions');
       return false;
@@ -31624,10 +24221,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
-
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
   static const abstract = SemanticTokenModifiers('abstract');
   static const async = SemanticTokenModifiers('async');
   static const declaration = SemanticTokenModifiers('declaration');
@@ -31663,10 +24257,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
-
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
   static const class_ = SemanticTokenTypes('class');
   static const comment = SemanticTokenTypes('comment');
 
@@ -31754,35 +24345,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('data');
-      try {
-        if (!obj.containsKey('data')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final data = obj['data'];
-        if (data == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (data is! List<Object?> || data.any((item) => item is! int)) {
-          reporter.reportError('must be of type List<int>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListInt(obj, reporter, 'data',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        final resultId = obj['resultId'];
-        if (resultId != null && resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'resultId',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokens');
       return false;
@@ -31939,135 +24507,41 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('augmentsSyntaxTokens');
-      try {
-        final augmentsSyntaxTokens = obj['augmentsSyntaxTokens'];
-        if (augmentsSyntaxTokens != null && augmentsSyntaxTokens is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'augmentsSyntaxTokens',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('formats');
-      try {
-        if (!obj.containsKey('formats')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final formats = obj['formats'];
-        if (formats == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (formats is! List<Object?> ||
-            formats.any((item) => !TokenFormat.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<TokenFormat>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTokenFormat(obj, reporter, 'formats',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('multilineTokenSupport');
-      try {
-        final multilineTokenSupport = obj['multilineTokenSupport'];
-        if (multilineTokenSupport != null && multilineTokenSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'multilineTokenSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('overlappingTokenSupport');
-      try {
-        final overlappingTokenSupport = obj['overlappingTokenSupport'];
-        if (overlappingTokenSupport != null &&
-            overlappingTokenSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'overlappingTokenSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('requests');
-      try {
-        if (!obj.containsKey('requests')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final requests = obj['requests'];
-        if (requests == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SemanticTokensClientCapabilitiesRequests.canParse(
-            requests, reporter)) {
-          reporter.reportError(
-              'must be of type SemanticTokensClientCapabilitiesRequests');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSemanticTokensClientCapabilitiesRequests(
+          obj, reporter, 'requests',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('serverCancelSupport');
-      try {
-        final serverCancelSupport = obj['serverCancelSupport'];
-        if (serverCancelSupport != null && serverCancelSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'serverCancelSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tokenModifiers');
-      try {
-        if (!obj.containsKey('tokenModifiers')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final tokenModifiers = obj['tokenModifiers'];
-        if (tokenModifiers == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (tokenModifiers is! List<Object?> ||
-            tokenModifiers.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'tokenModifiers',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tokenTypes');
-      try {
-        if (!obj.containsKey('tokenTypes')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final tokenTypes = obj['tokenTypes'];
-        if (tokenTypes == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (tokenTypes is! List<Object?> ||
-            tokenTypes.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'tokenTypes',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensClientCapabilities');
       return false;
@@ -32156,35 +24630,14 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('full');
-      try {
-        final full = obj['full'];
-        if (full != null &&
-            full is! bool &&
-            !SemanticTokensClientCapabilitiesRequestsFull.canParse(
-                full, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolSemanticTokensClientCapabilitiesRequestsFull(
+          obj, reporter, 'full',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        final range = obj['range'];
-        if (range != null &&
-            range is! bool &&
-            !SemanticTokensClientCapabilitiesRequestsRange.canParse(
-                range, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBoolSemanticTokensClientCapabilitiesRequestsRange(
+          obj, reporter, 'range',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type SemanticTokensClientCapabilitiesRequests');
@@ -32243,17 +24696,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('delta');
-      try {
-        final delta = obj['delta'];
-        if (delta != null && delta is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'delta',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type SemanticTokensClientCapabilitiesRequestsFull');
@@ -32353,36 +24797,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('edits');
-      try {
-        if (!obj.containsKey('edits')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final edits = obj['edits'];
-        if (edits == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (edits is! List<Object?> ||
-            edits.any((item) => !SemanticTokensEdit.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<SemanticTokensEdit>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListSemanticTokensEdit(obj, reporter, 'edits',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        final resultId = obj['resultId'];
-        if (resultId != null && resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'resultId',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensDelta');
       return false;
@@ -32475,67 +24895,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('previousResultId');
-      try {
-        if (!obj.containsKey('previousResultId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final previousResultId = obj['previousResultId'];
-        if (previousResultId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (previousResultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'previousResultId',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensDeltaParams');
       return false;
@@ -32596,26 +24969,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('edits');
-      try {
-        if (!obj.containsKey('edits')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final edits = obj['edits'];
-        if (edits == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (edits is! List<Object?> ||
-            edits.any((item) => !SemanticTokensEdit.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<SemanticTokensEdit>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSemanticTokensEdit(obj, reporter, 'edits',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensDeltaPartialResult');
       return false;
@@ -32686,54 +25041,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('data');
-      try {
-        final data = obj['data'];
-        if (data != null &&
-            (data is! List<Object?> || data.any((item) => item is! int))) {
-          reporter.reportError('must be of type List<int>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListInt(obj, reporter, 'data',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('deleteCount');
-      try {
-        if (!obj.containsKey('deleteCount')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final deleteCount = obj['deleteCount'];
-        if (deleteCount == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (deleteCount is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'deleteCount',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('start');
-      try {
-        if (!obj.containsKey('start')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final start = obj['start'];
-        if (start == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (start is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'start',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensEdit');
       return false;
@@ -32802,45 +25119,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('tokenModifiers');
-      try {
-        if (!obj.containsKey('tokenModifiers')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final tokenModifiers = obj['tokenModifiers'];
-        if (tokenModifiers == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (tokenModifiers is! List<Object?> ||
-            tokenModifiers.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'tokenModifiers',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tokenTypes');
-      try {
-        if (!obj.containsKey('tokenTypes')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final tokenTypes = obj['tokenTypes'];
-        if (tokenTypes == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (tokenTypes is! List<Object?> ||
-            tokenTypes.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'tokenTypes',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensLegend');
       return false;
@@ -32934,61 +25218,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('full');
-      try {
-        final full = obj['full'];
-        if (full != null &&
-            full is! bool &&
-            !SemanticTokensOptionsFull.canParse(full, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, SemanticTokensOptionsFull>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolSemanticTokensOptionsFull(obj, reporter, 'full',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('legend');
-      try {
-        if (!obj.containsKey('legend')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final legend = obj['legend'];
-        if (legend == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SemanticTokensLegend.canParse(legend, reporter)) {
-          reporter.reportError('must be of type SemanticTokensLegend');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSemanticTokensLegend(obj, reporter, 'legend',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        final range = obj['range'];
-        if (range != null &&
-            range is! bool &&
-            !SemanticTokensOptionsRange.canParse(range, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, SemanticTokensOptionsRange>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolSemanticTokensOptionsRange(obj, reporter, 'range',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensOptions');
       return false;
@@ -33048,17 +25291,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('delta');
-      try {
-        final delta = obj['delta'];
-        if (delta != null && delta is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'delta',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensOptionsFull');
       return false;
@@ -33172,49 +25406,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensParams');
       return false;
@@ -33271,25 +25472,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('data');
-      try {
-        if (!obj.containsKey('data')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final data = obj['data'];
-        if (data == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (data is! List<Object?> || data.any((item) => item is! int)) {
-          reporter.reportError('must be of type List<int>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListInt(obj, reporter, 'data',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensPartialResult');
       return false;
@@ -33376,67 +25560,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensRangeParams');
       return false;
@@ -33563,89 +25700,29 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('full');
-      try {
-        final full = obj['full'];
-        if (full != null &&
-            full is! bool &&
-            !SemanticTokensOptionsFull.canParse(full, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, SemanticTokensOptionsFull>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolSemanticTokensOptionsFull(obj, reporter, 'full',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('legend');
-      try {
-        if (!obj.containsKey('legend')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final legend = obj['legend'];
-        if (legend == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SemanticTokensLegend.canParse(legend, reporter)) {
-          reporter.reportError('must be of type SemanticTokensLegend');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSemanticTokensLegend(obj, reporter, 'legend',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        final range = obj['range'];
-        if (range != null &&
-            range is! bool &&
-            !SemanticTokensOptionsRange.canParse(range, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, SemanticTokensOptionsRange>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolSemanticTokensOptionsRange(obj, reporter, 'range',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SemanticTokensRegistrationOptions');
       return false;
@@ -33721,17 +25798,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('refreshSupport');
-      try {
-        final refreshSupport = obj['refreshSupport'];
-        if (refreshSupport != null && refreshSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'refreshSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type SemanticTokensWorkspaceClientCapabilities');
@@ -34271,467 +26339,163 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('callHierarchyProvider');
-      try {
-        final callHierarchyProvider = obj['callHierarchyProvider'];
-        if (callHierarchyProvider != null &&
-            callHierarchyProvider is! bool &&
-            !CallHierarchyOptions.canParse(callHierarchyProvider, reporter) &&
-            !CallHierarchyRegistrationOptions.canParse(
-                callHierarchyProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolCallHierarchyOptionsCallHierarchyRegistrationOptions(
+          obj, reporter, 'callHierarchyProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeActionProvider');
-      try {
-        final codeActionProvider = obj['codeActionProvider'];
-        if (codeActionProvider != null &&
-            codeActionProvider is! bool &&
-            !CodeActionOptions.canParse(codeActionProvider, reporter)) {
-          reporter
-              .reportError('must be of type Either2<bool, CodeActionOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolCodeActionOptions(obj, reporter, 'codeActionProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeLensProvider');
-      try {
-        final codeLensProvider = obj['codeLensProvider'];
-        if (codeLensProvider != null &&
-            !CodeLensOptions.canParse(codeLensProvider, reporter)) {
-          reporter.reportError('must be of type CodeLensOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeLensOptions(obj, reporter, 'codeLensProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('colorProvider');
-      try {
-        final colorProvider = obj['colorProvider'];
-        if (colorProvider != null &&
-            colorProvider is! bool &&
-            !DocumentColorOptions.canParse(colorProvider, reporter) &&
-            !DocumentColorRegistrationOptions.canParse(
-                colorProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolDocumentColorOptionsDocumentColorRegistrationOptions(
+          obj, reporter, 'colorProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('completionProvider');
-      try {
-        final completionProvider = obj['completionProvider'];
-        if (completionProvider != null &&
-            !CompletionOptions.canParse(completionProvider, reporter)) {
-          reporter.reportError('must be of type CompletionOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionOptions(obj, reporter, 'completionProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('declarationProvider');
-      try {
-        final declarationProvider = obj['declarationProvider'];
-        if (declarationProvider != null &&
-            declarationProvider is! bool &&
-            !DeclarationOptions.canParse(declarationProvider, reporter) &&
-            !DeclarationRegistrationOptions.canParse(
-                declarationProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolDeclarationOptionsDeclarationRegistrationOptions(
+          obj, reporter, 'declarationProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('definitionProvider');
-      try {
-        final definitionProvider = obj['definitionProvider'];
-        if (definitionProvider != null &&
-            definitionProvider is! bool &&
-            !DefinitionOptions.canParse(definitionProvider, reporter)) {
-          reporter
-              .reportError('must be of type Either2<bool, DefinitionOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolDefinitionOptions(obj, reporter, 'definitionProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('diagnosticProvider');
-      try {
-        final diagnosticProvider = obj['diagnosticProvider'];
-        if (diagnosticProvider != null &&
-            !DiagnosticOptions.canParse(diagnosticProvider, reporter) &&
-            !DiagnosticRegistrationOptions.canParse(
-                diagnosticProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<DiagnosticOptions, DiagnosticRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDiagnosticOptionsDiagnosticRegistrationOptions(
+          obj, reporter, 'diagnosticProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentFormattingProvider');
-      try {
-        final documentFormattingProvider = obj['documentFormattingProvider'];
-        if (documentFormattingProvider != null &&
-            documentFormattingProvider is! bool &&
-            !DocumentFormattingOptions.canParse(
-                documentFormattingProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, DocumentFormattingOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolDocumentFormattingOptions(
+          obj, reporter, 'documentFormattingProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentHighlightProvider');
-      try {
-        final documentHighlightProvider = obj['documentHighlightProvider'];
-        if (documentHighlightProvider != null &&
-            documentHighlightProvider is! bool &&
-            !DocumentHighlightOptions.canParse(
-                documentHighlightProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, DocumentHighlightOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolDocumentHighlightOptions(
+          obj, reporter, 'documentHighlightProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentLinkProvider');
-      try {
-        final documentLinkProvider = obj['documentLinkProvider'];
-        if (documentLinkProvider != null &&
-            !DocumentLinkOptions.canParse(documentLinkProvider, reporter)) {
-          reporter.reportError('must be of type DocumentLinkOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentLinkOptions(obj, reporter, 'documentLinkProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentOnTypeFormattingProvider');
-      try {
-        final documentOnTypeFormattingProvider =
-            obj['documentOnTypeFormattingProvider'];
-        if (documentOnTypeFormattingProvider != null &&
-            !DocumentOnTypeFormattingOptions.canParse(
-                documentOnTypeFormattingProvider, reporter)) {
-          reporter
-              .reportError('must be of type DocumentOnTypeFormattingOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentOnTypeFormattingOptions(
+          obj, reporter, 'documentOnTypeFormattingProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentRangeFormattingProvider');
-      try {
-        final documentRangeFormattingProvider =
-            obj['documentRangeFormattingProvider'];
-        if (documentRangeFormattingProvider != null &&
-            documentRangeFormattingProvider is! bool &&
-            !DocumentRangeFormattingOptions.canParse(
-                documentRangeFormattingProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, DocumentRangeFormattingOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolDocumentRangeFormattingOptions(
+          obj, reporter, 'documentRangeFormattingProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentSymbolProvider');
-      try {
-        final documentSymbolProvider = obj['documentSymbolProvider'];
-        if (documentSymbolProvider != null &&
-            documentSymbolProvider is! bool &&
-            !DocumentSymbolOptions.canParse(documentSymbolProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, DocumentSymbolOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolDocumentSymbolOptions(
+          obj, reporter, 'documentSymbolProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('executeCommandProvider');
-      try {
-        final executeCommandProvider = obj['executeCommandProvider'];
-        if (executeCommandProvider != null &&
-            !ExecuteCommandOptions.canParse(executeCommandProvider, reporter)) {
-          reporter.reportError('must be of type ExecuteCommandOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseExecuteCommandOptions(
+          obj, reporter, 'executeCommandProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('foldingRangeProvider');
-      try {
-        final foldingRangeProvider = obj['foldingRangeProvider'];
-        if (foldingRangeProvider != null &&
-            foldingRangeProvider is! bool &&
-            !FoldingRangeOptions.canParse(foldingRangeProvider, reporter) &&
-            !FoldingRangeRegistrationOptions.canParse(
-                foldingRangeProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolFoldingRangeOptionsFoldingRangeRegistrationOptions(
+          obj, reporter, 'foldingRangeProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('hoverProvider');
-      try {
-        final hoverProvider = obj['hoverProvider'];
-        if (hoverProvider != null &&
-            hoverProvider is! bool &&
-            !HoverOptions.canParse(hoverProvider, reporter)) {
-          reporter.reportError('must be of type Either2<bool, HoverOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolHoverOptions(obj, reporter, 'hoverProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('implementationProvider');
-      try {
-        final implementationProvider = obj['implementationProvider'];
-        if (implementationProvider != null &&
-            implementationProvider is! bool &&
-            !ImplementationOptions.canParse(implementationProvider, reporter) &&
-            !ImplementationRegistrationOptions.canParse(
-                implementationProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolImplementationOptionsImplementationRegistrationOptions(
+          obj, reporter, 'implementationProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('inlayHintProvider');
-      try {
-        final inlayHintProvider = obj['inlayHintProvider'];
-        if (inlayHintProvider != null &&
-            inlayHintProvider is! bool &&
-            !InlayHintOptions.canParse(inlayHintProvider, reporter) &&
-            !InlayHintRegistrationOptions.canParse(
-                inlayHintProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolInlayHintOptionsInlayHintRegistrationOptions(
+          obj, reporter, 'inlayHintProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('inlineValueProvider');
-      try {
-        final inlineValueProvider = obj['inlineValueProvider'];
-        if (inlineValueProvider != null &&
-            inlineValueProvider is! bool &&
-            !InlineValueOptions.canParse(inlineValueProvider, reporter) &&
-            !InlineValueRegistrationOptions.canParse(
-                inlineValueProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolInlineValueOptionsInlineValueRegistrationOptions(
+          obj, reporter, 'inlineValueProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('linkedEditingRangeProvider');
-      try {
-        final linkedEditingRangeProvider = obj['linkedEditingRangeProvider'];
-        if (linkedEditingRangeProvider != null &&
-            linkedEditingRangeProvider is! bool &&
-            !LinkedEditingRangeOptions.canParse(
-                linkedEditingRangeProvider, reporter) &&
-            !LinkedEditingRangeRegistrationOptions.canParse(
-                linkedEditingRangeProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolLinkedEditingRangeOptionsLinkedEditingRangeRegistrationOptions(
+          obj, reporter, 'linkedEditingRangeProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('monikerProvider');
-      try {
-        final monikerProvider = obj['monikerProvider'];
-        if (monikerProvider != null &&
-            monikerProvider is! bool &&
-            !MonikerOptions.canParse(monikerProvider, reporter) &&
-            !MonikerRegistrationOptions.canParse(monikerProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, MonikerOptions, MonikerRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolMonikerOptionsMonikerRegistrationOptions(
+          obj, reporter, 'monikerProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('notebookDocumentSync');
-      try {
-        final notebookDocumentSync = obj['notebookDocumentSync'];
-        if (notebookDocumentSync != null &&
-            !NotebookDocumentSyncOptions.canParse(
-                notebookDocumentSync, reporter) &&
-            !NotebookDocumentSyncRegistrationOptions.canParse(
-                notebookDocumentSync, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseNotebookDocumentSyncOptionsNotebookDocumentSyncRegistrationOptions(
+          obj, reporter, 'notebookDocumentSync',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('positionEncoding');
-      try {
-        final positionEncoding = obj['positionEncoding'];
-        if (positionEncoding != null &&
-            !PositionEncodingKind.canParse(positionEncoding, reporter)) {
-          reporter.reportError('must be of type PositionEncodingKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePositionEncodingKind(obj, reporter, 'positionEncoding',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('referencesProvider');
-      try {
-        final referencesProvider = obj['referencesProvider'];
-        if (referencesProvider != null &&
-            referencesProvider is! bool &&
-            !ReferenceOptions.canParse(referencesProvider, reporter)) {
-          reporter
-              .reportError('must be of type Either2<bool, ReferenceOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolReferenceOptions(obj, reporter, 'referencesProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('renameProvider');
-      try {
-        final renameProvider = obj['renameProvider'];
-        if (renameProvider != null &&
-            renameProvider is! bool &&
-            !RenameOptions.canParse(renameProvider, reporter)) {
-          reporter.reportError('must be of type Either2<bool, RenameOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolRenameOptions(obj, reporter, 'renameProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('selectionRangeProvider');
-      try {
-        final selectionRangeProvider = obj['selectionRangeProvider'];
-        if (selectionRangeProvider != null &&
-            selectionRangeProvider is! bool &&
-            !SelectionRangeOptions.canParse(selectionRangeProvider, reporter) &&
-            !SelectionRangeRegistrationOptions.canParse(
-                selectionRangeProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolSelectionRangeOptionsSelectionRangeRegistrationOptions(
+          obj, reporter, 'selectionRangeProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('semanticTokensProvider');
-      try {
-        final semanticTokensProvider = obj['semanticTokensProvider'];
-        if (semanticTokensProvider != null &&
-            !SemanticTokensOptions.canParse(semanticTokensProvider, reporter) &&
-            !SemanticTokensRegistrationOptions.canParse(
-                semanticTokensProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSemanticTokensOptionsSemanticTokensRegistrationOptions(
+          obj, reporter, 'semanticTokensProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('signatureHelpProvider');
-      try {
-        final signatureHelpProvider = obj['signatureHelpProvider'];
-        if (signatureHelpProvider != null &&
-            !SignatureHelpOptions.canParse(signatureHelpProvider, reporter)) {
-          reporter.reportError('must be of type SignatureHelpOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSignatureHelpOptions(obj, reporter, 'signatureHelpProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocumentSync');
-      try {
-        final textDocumentSync = obj['textDocumentSync'];
-        if (textDocumentSync != null &&
-            !TextDocumentSyncKind.canParse(textDocumentSync, reporter) &&
-            !TextDocumentSyncOptions.canParse(textDocumentSync, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<TextDocumentSyncKind, TextDocumentSyncOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentSyncKindTextDocumentSyncOptions(
+          obj, reporter, 'textDocumentSync',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('typeDefinitionProvider');
-      try {
-        final typeDefinitionProvider = obj['typeDefinitionProvider'];
-        if (typeDefinitionProvider != null &&
-            typeDefinitionProvider is! bool &&
-            !TypeDefinitionOptions.canParse(typeDefinitionProvider, reporter) &&
-            !TypeDefinitionRegistrationOptions.canParse(
-                typeDefinitionProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolTypeDefinitionOptionsTypeDefinitionRegistrationOptions(
+          obj, reporter, 'typeDefinitionProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('typeHierarchyProvider');
-      try {
-        final typeHierarchyProvider = obj['typeHierarchyProvider'];
-        if (typeHierarchyProvider != null &&
-            typeHierarchyProvider is! bool &&
-            !TypeHierarchyOptions.canParse(typeHierarchyProvider, reporter) &&
-            !TypeHierarchyRegistrationOptions.canParse(
-                typeHierarchyProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolTypeHierarchyOptionsTypeHierarchyRegistrationOptions(
+          obj, reporter, 'typeHierarchyProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspace');
-      try {
-        final workspace = obj['workspace'];
-        if (workspace != null &&
-            !ServerCapabilitiesWorkspace.canParse(workspace, reporter)) {
-          reporter.reportError('must be of type ServerCapabilitiesWorkspace');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseServerCapabilitiesWorkspace(obj, reporter, 'workspace',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspaceSymbolProvider');
-      try {
-        final workspaceSymbolProvider = obj['workspaceSymbolProvider'];
-        if (workspaceSymbolProvider != null &&
-            workspaceSymbolProvider is! bool &&
-            !WorkspaceSymbolOptions.canParse(
-                workspaceSymbolProvider, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<bool, WorkspaceSymbolOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBoolWorkspaceSymbolOptions(
+          obj, reporter, 'workspaceSymbolProvider',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ServerCapabilities');
       return false;
@@ -34876,31 +26640,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('fileOperations');
-      try {
-        final fileOperations = obj['fileOperations'];
-        if (fileOperations != null &&
-            !FileOperationOptions.canParse(fileOperations, reporter)) {
-          reporter.reportError('must be of type FileOperationOptions');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationOptions(obj, reporter, 'fileOperations',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspaceFolders');
-      try {
-        final workspaceFolders = obj['workspaceFolders'];
-        if (workspaceFolders != null &&
-            !WorkspaceFoldersServerCapabilities.canParse(
-                workspaceFolders, reporter)) {
-          reporter.reportError(
-              'must be of type WorkspaceFoldersServerCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseWorkspaceFoldersServerCapabilities(
+          obj, reporter, 'workspaceFolders',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type ServerCapabilitiesWorkspace');
       return false;
@@ -34953,25 +26699,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('value');
-      try {
-        if (!obj.containsKey('value')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final value = obj['value'];
-        if (value == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TraceValues.canParse(value, reporter)) {
-          reporter.reportError('must be of type TraceValues');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTraceValues(obj, reporter, 'value',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SetTraceParams');
       return false;
@@ -35024,25 +26753,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('support');
-      try {
-        if (!obj.containsKey('support')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final support = obj['support'];
-        if (support == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (support is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'support',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ShowDocumentClientCapabilities');
       return false;
@@ -35133,55 +26845,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('external');
-      try {
-        final external = obj['external'];
-        if (external != null && external is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'external',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('selection');
-      try {
-        final selection = obj['selection'];
-        if (selection != null && !Range.canParse(selection, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'selection',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('takeFocus');
-      try {
-        final takeFocus = obj['takeFocus'];
-        if (takeFocus != null && takeFocus is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'takeFocus',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ShowDocumentParams');
       return false;
@@ -35242,25 +26919,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('success');
-      try {
-        if (!obj.containsKey('success')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final success = obj['success'];
-        if (success == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (success is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'success',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ShowDocumentResult');
       return false;
@@ -35319,43 +26979,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('message');
-      try {
-        if (!obj.containsKey('message')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final message = obj['message'];
-        if (message == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('type');
-      try {
-        if (!obj.containsKey('type')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final type = obj['type'];
-        if (type == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!MessageType.canParse(type, reporter)) {
-          reporter.reportError('must be of type MessageType');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMessageType(obj, reporter, 'type',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ShowMessageParams');
       return false;
@@ -35417,20 +27046,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('messageActionItem');
-      try {
-        final messageActionItem = obj['messageActionItem'];
-        if (messageActionItem != null &&
-            !ShowMessageRequestClientCapabilitiesMessageActionItem.canParse(
-                messageActionItem, reporter)) {
-          reporter.reportError(
-              'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseShowMessageRequestClientCapabilitiesMessageActionItem(
+          obj, reporter, 'messageActionItem',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type ShowMessageRequestClientCapabilities');
@@ -35487,18 +27105,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('additionalPropertiesSupport');
-      try {
-        final additionalPropertiesSupport = obj['additionalPropertiesSupport'];
-        if (additionalPropertiesSupport != null &&
-            additionalPropertiesSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'additionalPropertiesSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
@@ -35571,56 +27179,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('actions');
-      try {
-        final actions = obj['actions'];
-        if (actions != null &&
-            (actions is! List<Object?> ||
-                actions.any(
-                    (item) => !MessageActionItem.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<MessageActionItem>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListMessageActionItem(obj, reporter, 'actions',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('message');
-      try {
-        if (!obj.containsKey('message')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final message = obj['message'];
-        if (message == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('type');
-      try {
-        if (!obj.containsKey('type')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final type = obj['type'];
-        if (type == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!MessageType.canParse(type, reporter)) {
-          reporter.reportError('must be of type MessageType');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseMessageType(obj, reporter, 'type',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type ShowMessageRequestParams');
       return false;
@@ -35715,47 +27283,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('activeParameter');
-      try {
-        final activeParameter = obj['activeParameter'];
-        if (activeParameter != null && activeParameter is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'activeParameter',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('activeSignature');
-      try {
-        final activeSignature = obj['activeSignature'];
-        if (activeSignature != null && activeSignature is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'activeSignature',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('signatures');
-      try {
-        if (!obj.containsKey('signatures')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final signatures = obj['signatures'];
-        if (signatures == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (signatures is! List<Object?> ||
-            signatures.any(
-                (item) => !SignatureInformation.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<SignatureInformation>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSignatureInformation(obj, reporter, 'signatures',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SignatureHelp');
       return false;
@@ -35845,40 +27382,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('contextSupport');
-      try {
-        final contextSupport = obj['contextSupport'];
-        if (contextSupport != null && contextSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'contextSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('signatureInformation');
-      try {
-        final signatureInformation = obj['signatureInformation'];
-        if (signatureInformation != null &&
-            !SignatureHelpClientCapabilitiesSignatureInformation.canParse(
-                signatureInformation, reporter)) {
-          reporter.reportError(
-              'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseSignatureHelpClientCapabilitiesSignatureInformation(
+          obj, reporter, 'signatureInformation',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SignatureHelpClientCapabilities');
       return false;
@@ -35968,43 +27482,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('activeParameterSupport');
-      try {
-        final activeParameterSupport = obj['activeParameterSupport'];
-        if (activeParameterSupport != null && activeParameterSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'activeParameterSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentationFormat');
-      try {
-        final documentationFormat = obj['documentationFormat'];
-        if (documentationFormat != null &&
-            (documentationFormat is! List<Object?> ||
-                documentationFormat
-                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<MarkupKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListMarkupKind(obj, reporter, 'documentationFormat',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('parameterInformation');
-      try {
-        final parameterInformation = obj['parameterInformation'];
-        if (parameterInformation != null &&
-            !SignatureInformationParameterInformation.canParse(
-                parameterInformation, reporter)) {
-          reporter.reportError(
-              'must be of type SignatureInformationParameterInformation');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseSignatureInformationParameterInformation(
+          obj, reporter, 'parameterInformation',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
@@ -36109,64 +27597,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('activeSignatureHelp');
-      try {
-        final activeSignatureHelp = obj['activeSignatureHelp'];
-        if (activeSignatureHelp != null &&
-            !SignatureHelp.canParse(activeSignatureHelp, reporter)) {
-          reporter.reportError('must be of type SignatureHelp');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSignatureHelp(obj, reporter, 'activeSignatureHelp',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('isRetrigger');
-      try {
-        if (!obj.containsKey('isRetrigger')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final isRetrigger = obj['isRetrigger'];
-        if (isRetrigger == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (isRetrigger is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'isRetrigger',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerCharacter');
-      try {
-        final triggerCharacter = obj['triggerCharacter'];
-        if (triggerCharacter != null && triggerCharacter is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'triggerCharacter',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerKind');
-      try {
-        if (!obj.containsKey('triggerKind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final triggerKind = obj['triggerKind'];
-        if (triggerKind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SignatureHelpTriggerKind.canParse(triggerKind, reporter)) {
-          reporter.reportError('must be of type SignatureHelpTriggerKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseSignatureHelpTriggerKind(obj, reporter, 'triggerKind',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type SignatureHelpContext');
       return false;
@@ -36258,41 +27702,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('retriggerCharacters');
-      try {
-        final retriggerCharacters = obj['retriggerCharacters'];
-        if (retriggerCharacters != null &&
-            (retriggerCharacters is! List<Object?> ||
-                retriggerCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'retriggerCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerCharacters');
-      try {
-        final triggerCharacters = obj['triggerCharacters'];
-        if (triggerCharacters != null &&
-            (triggerCharacters is! List<Object?> ||
-                triggerCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'triggerCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SignatureHelpOptions');
       return false;
@@ -36391,66 +27810,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('context');
-      try {
-        final context = obj['context'];
-        if (context != null &&
-            !SignatureHelpContext.canParse(context, reporter)) {
-          reporter.reportError('must be of type SignatureHelpContext');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSignatureHelpContext(obj, reporter, 'context',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SignatureHelpParams');
       return false;
@@ -36558,59 +27931,21 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('retriggerCharacters');
-      try {
-        final retriggerCharacters = obj['retriggerCharacters'];
-        if (retriggerCharacters != null &&
-            (retriggerCharacters is! List<Object?> ||
-                retriggerCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'retriggerCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('triggerCharacters');
-      try {
-        final triggerCharacters = obj['triggerCharacters'];
-        if (triggerCharacters != null &&
-            (triggerCharacters is! List<Object?> ||
-                triggerCharacters.any((item) => item is! String))) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListString(obj, reporter, 'triggerCharacters',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SignatureHelpRegistrationOptions');
       return false;
@@ -36654,9 +27989,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Signature help was triggered by the cursor moving or by the document
   /// content changing.
@@ -36753,61 +28086,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('activeParameter');
-      try {
-        final activeParameter = obj['activeParameter'];
-        if (activeParameter != null && activeParameter is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'activeParameter',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentation');
-      try {
-        final documentation = obj['documentation'];
-        if (documentation != null &&
-            !MarkupContent.canParse(documentation, reporter) &&
-            documentation is! String) {
-          reporter
-              .reportError('must be of type Either2<MarkupContent, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMarkupContentString(obj, reporter, 'documentation',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('label');
-      try {
-        if (!obj.containsKey('label')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final label = obj['label'];
-        if (label == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (label is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'label',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('parameters');
-      try {
-        final parameters = obj['parameters'];
-        if (parameters != null &&
-            (parameters is! List<Object?> ||
-                parameters.any((item) =>
-                    !ParameterInformation.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<ParameterInformation>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListParameterInformation(obj, reporter, 'parameters',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SignatureInformation');
       return false;
@@ -36872,17 +28164,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('labelOffsetSupport');
-      try {
-        final labelOffsetSupport = obj['labelOffsetSupport'];
-        if (labelOffsetSupport != null && labelOffsetSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'labelOffsetSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type SignatureInformationParameterInformation');
@@ -36981,17 +28264,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type StaticRegistrationOptions');
       return false;
@@ -37110,93 +28384,28 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('containerName');
-      try {
-        final containerName = obj['containerName'];
-        if (containerName != null && containerName is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'containerName',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('deprecated');
-      try {
-        final deprecated = obj['deprecated'];
-        if (deprecated != null && deprecated is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'deprecated',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SymbolKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type SymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSymbolKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('location');
-      try {
-        if (!obj.containsKey('location')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final location = obj['location'];
-        if (location == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Location.canParse(location, reporter)) {
-          reporter.reportError('must be of type Location');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLocation(obj, reporter, 'location',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type SymbolInformation');
       return false;
@@ -37236,10 +28445,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
-
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
   static const Array = SymbolKind(18);
   static const Boolean = SymbolKind(17);
   static const Class = SymbolKind(5);
@@ -37290,9 +28496,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Render a symbol as obsolete, usually using a strike-out.
   static const Deprecated = SymbolTag(1);
@@ -37356,43 +28560,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('syncKind');
-      try {
-        if (!obj.containsKey('syncKind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final syncKind = obj['syncKind'];
-        if (syncKind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentSyncKind.canParse(syncKind, reporter)) {
-          reporter.reportError('must be of type TextDocumentSyncKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextDocumentSyncKind(obj, reporter, 'syncKind',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type TextDocumentChangeRegistrationOptions');
@@ -37862,371 +29036,142 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('callHierarchy');
-      try {
-        final callHierarchy = obj['callHierarchy'];
-        if (callHierarchy != null &&
-            !CallHierarchyClientCapabilities.canParse(
-                callHierarchy, reporter)) {
-          reporter
-              .reportError('must be of type CallHierarchyClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCallHierarchyClientCapabilities(
+          obj, reporter, 'callHierarchy',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeAction');
-      try {
-        final codeAction = obj['codeAction'];
-        if (codeAction != null &&
-            !CodeActionClientCapabilities.canParse(codeAction, reporter)) {
-          reporter.reportError('must be of type CodeActionClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeActionClientCapabilities(obj, reporter, 'codeAction',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeLens');
-      try {
-        final codeLens = obj['codeLens'];
-        if (codeLens != null &&
-            !CodeLensClientCapabilities.canParse(codeLens, reporter)) {
-          reporter.reportError('must be of type CodeLensClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeLensClientCapabilities(obj, reporter, 'codeLens',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('colorProvider');
-      try {
-        final colorProvider = obj['colorProvider'];
-        if (colorProvider != null &&
-            !DocumentColorClientCapabilities.canParse(
-                colorProvider, reporter)) {
-          reporter
-              .reportError('must be of type DocumentColorClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentColorClientCapabilities(
+          obj, reporter, 'colorProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('completion');
-      try {
-        final completion = obj['completion'];
-        if (completion != null &&
-            !CompletionClientCapabilities.canParse(completion, reporter)) {
-          reporter.reportError('must be of type CompletionClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCompletionClientCapabilities(obj, reporter, 'completion',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('declaration');
-      try {
-        final declaration = obj['declaration'];
-        if (declaration != null &&
-            !DeclarationClientCapabilities.canParse(declaration, reporter)) {
-          reporter.reportError('must be of type DeclarationClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDeclarationClientCapabilities(obj, reporter, 'declaration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('definition');
-      try {
-        final definition = obj['definition'];
-        if (definition != null &&
-            !DefinitionClientCapabilities.canParse(definition, reporter)) {
-          reporter.reportError('must be of type DefinitionClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDefinitionClientCapabilities(obj, reporter, 'definition',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('diagnostic');
-      try {
-        final diagnostic = obj['diagnostic'];
-        if (diagnostic != null &&
-            !DiagnosticClientCapabilities.canParse(diagnostic, reporter)) {
-          reporter.reportError('must be of type DiagnosticClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDiagnosticClientCapabilities(obj, reporter, 'diagnostic',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentHighlight');
-      try {
-        final documentHighlight = obj['documentHighlight'];
-        if (documentHighlight != null &&
-            !DocumentHighlightClientCapabilities.canParse(
-                documentHighlight, reporter)) {
-          reporter.reportError(
-              'must be of type DocumentHighlightClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentHighlightClientCapabilities(
+          obj, reporter, 'documentHighlight',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentLink');
-      try {
-        final documentLink = obj['documentLink'];
-        if (documentLink != null &&
-            !DocumentLinkClientCapabilities.canParse(documentLink, reporter)) {
-          reporter
-              .reportError('must be of type DocumentLinkClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentLinkClientCapabilities(
+          obj, reporter, 'documentLink',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentSymbol');
-      try {
-        final documentSymbol = obj['documentSymbol'];
-        if (documentSymbol != null &&
-            !DocumentSymbolClientCapabilities.canParse(
-                documentSymbol, reporter)) {
-          reporter
-              .reportError('must be of type DocumentSymbolClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentSymbolClientCapabilities(
+          obj, reporter, 'documentSymbol',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('foldingRange');
-      try {
-        final foldingRange = obj['foldingRange'];
-        if (foldingRange != null &&
-            !FoldingRangeClientCapabilities.canParse(foldingRange, reporter)) {
-          reporter
-              .reportError('must be of type FoldingRangeClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFoldingRangeClientCapabilities(
+          obj, reporter, 'foldingRange',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('formatting');
-      try {
-        final formatting = obj['formatting'];
-        if (formatting != null &&
-            !DocumentFormattingClientCapabilities.canParse(
-                formatting, reporter)) {
-          reporter.reportError(
-              'must be of type DocumentFormattingClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentFormattingClientCapabilities(
+          obj, reporter, 'formatting',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('hover');
-      try {
-        final hover = obj['hover'];
-        if (hover != null &&
-            !HoverClientCapabilities.canParse(hover, reporter)) {
-          reporter.reportError('must be of type HoverClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseHoverClientCapabilities(obj, reporter, 'hover',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('implementation');
-      try {
-        final implementation = obj['implementation'];
-        if (implementation != null &&
-            !ImplementationClientCapabilities.canParse(
-                implementation, reporter)) {
-          reporter
-              .reportError('must be of type ImplementationClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseImplementationClientCapabilities(
+          obj, reporter, 'implementation',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('inlayHint');
-      try {
-        final inlayHint = obj['inlayHint'];
-        if (inlayHint != null &&
-            !InlayHintClientCapabilities.canParse(inlayHint, reporter)) {
-          reporter.reportError('must be of type InlayHintClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInlayHintClientCapabilities(obj, reporter, 'inlayHint',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('inlineValue');
-      try {
-        final inlineValue = obj['inlineValue'];
-        if (inlineValue != null &&
-            !InlineValueClientCapabilities.canParse(inlineValue, reporter)) {
-          reporter.reportError('must be of type InlineValueClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInlineValueClientCapabilities(obj, reporter, 'inlineValue',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('linkedEditingRange');
-      try {
-        final linkedEditingRange = obj['linkedEditingRange'];
-        if (linkedEditingRange != null &&
-            !LinkedEditingRangeClientCapabilities.canParse(
-                linkedEditingRange, reporter)) {
-          reporter.reportError(
-              'must be of type LinkedEditingRangeClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLinkedEditingRangeClientCapabilities(
+          obj, reporter, 'linkedEditingRange',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('moniker');
-      try {
-        final moniker = obj['moniker'];
-        if (moniker != null &&
-            !MonikerClientCapabilities.canParse(moniker, reporter)) {
-          reporter.reportError('must be of type MonikerClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMonikerClientCapabilities(obj, reporter, 'moniker',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('onTypeFormatting');
-      try {
-        final onTypeFormatting = obj['onTypeFormatting'];
-        if (onTypeFormatting != null &&
-            !DocumentOnTypeFormattingClientCapabilities.canParse(
-                onTypeFormatting, reporter)) {
-          reporter.reportError(
-              'must be of type DocumentOnTypeFormattingClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentOnTypeFormattingClientCapabilities(
+          obj, reporter, 'onTypeFormatting',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('publishDiagnostics');
-      try {
-        final publishDiagnostics = obj['publishDiagnostics'];
-        if (publishDiagnostics != null &&
-            !PublishDiagnosticsClientCapabilities.canParse(
-                publishDiagnostics, reporter)) {
-          reporter.reportError(
-              'must be of type PublishDiagnosticsClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePublishDiagnosticsClientCapabilities(
+          obj, reporter, 'publishDiagnostics',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('rangeFormatting');
-      try {
-        final rangeFormatting = obj['rangeFormatting'];
-        if (rangeFormatting != null &&
-            !DocumentRangeFormattingClientCapabilities.canParse(
-                rangeFormatting, reporter)) {
-          reporter.reportError(
-              'must be of type DocumentRangeFormattingClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDocumentRangeFormattingClientCapabilities(
+          obj, reporter, 'rangeFormatting',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('references');
-      try {
-        final references = obj['references'];
-        if (references != null &&
-            !ReferenceClientCapabilities.canParse(references, reporter)) {
-          reporter.reportError('must be of type ReferenceClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseReferenceClientCapabilities(obj, reporter, 'references',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('rename');
-      try {
-        final rename = obj['rename'];
-        if (rename != null &&
-            !RenameClientCapabilities.canParse(rename, reporter)) {
-          reporter.reportError('must be of type RenameClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRenameClientCapabilities(obj, reporter, 'rename',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('selectionRange');
-      try {
-        final selectionRange = obj['selectionRange'];
-        if (selectionRange != null &&
-            !SelectionRangeClientCapabilities.canParse(
-                selectionRange, reporter)) {
-          reporter
-              .reportError('must be of type SelectionRangeClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSelectionRangeClientCapabilities(
+          obj, reporter, 'selectionRange',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('semanticTokens');
-      try {
-        final semanticTokens = obj['semanticTokens'];
-        if (semanticTokens != null &&
-            !SemanticTokensClientCapabilities.canParse(
-                semanticTokens, reporter)) {
-          reporter
-              .reportError('must be of type SemanticTokensClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSemanticTokensClientCapabilities(
+          obj, reporter, 'semanticTokens',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('signatureHelp');
-      try {
-        final signatureHelp = obj['signatureHelp'];
-        if (signatureHelp != null &&
-            !SignatureHelpClientCapabilities.canParse(
-                signatureHelp, reporter)) {
-          reporter
-              .reportError('must be of type SignatureHelpClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSignatureHelpClientCapabilities(
+          obj, reporter, 'signatureHelp',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('synchronization');
-      try {
-        final synchronization = obj['synchronization'];
-        if (synchronization != null &&
-            !TextDocumentSyncClientCapabilities.canParse(
-                synchronization, reporter)) {
-          reporter.reportError(
-              'must be of type TextDocumentSyncClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentSyncClientCapabilities(
+          obj, reporter, 'synchronization',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('typeDefinition');
-      try {
-        final typeDefinition = obj['typeDefinition'];
-        if (typeDefinition != null &&
-            !TypeDefinitionClientCapabilities.canParse(
-                typeDefinition, reporter)) {
-          reporter
-              .reportError('must be of type TypeDefinitionClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTypeDefinitionClientCapabilities(
+          obj, reporter, 'typeDefinition',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('typeHierarchy');
-      try {
-        final typeHierarchy = obj['typeHierarchy'];
-        if (typeHierarchy != null &&
-            !TypeHierarchyClientCapabilities.canParse(
-                typeHierarchy, reporter)) {
-          reporter
-              .reportError('must be of type TypeHierarchyClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTypeHierarchyClientCapabilities(
+          obj, reporter, 'typeHierarchy',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentClientCapabilities');
       return false;
@@ -38356,53 +29301,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('rangeLength');
-      try {
-        final rangeLength = obj['rangeLength'];
-        if (rangeLength != null && rangeLength is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'rangeLength',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('text');
-      try {
-        if (!obj.containsKey('text')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final text = obj['text'];
-        if (text == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (text is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'text',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentContentChangeEvent1');
       return false;
@@ -38458,25 +29366,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('text');
-      try {
-        if (!obj.containsKey('text')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final text = obj['text'];
-        if (text == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (text is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'text',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentContentChangeEvent2');
       return false;
@@ -38545,50 +29436,14 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('edits');
-      try {
-        if (!obj.containsKey('edits')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final edits = obj['edits'];
-        if (edits == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (edits is! List<Object?> ||
-            edits.any((item) =>
-                !AnnotatedTextEdit.canParse(item, reporter) &&
-                !SnippetTextEdit.canParse(item, reporter) &&
-                !TextEdit.canParse(item, reporter))) {
-          reporter.reportError(
-              'must be of type List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListAnnotatedTextEditSnippetTextEditTextEdit(
+          obj, reporter, 'edits',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!OptionalVersionedTextDocumentIdentifier.canParse(
-            textDocument, reporter)) {
-          reporter.reportError(
-              'must be of type OptionalVersionedTextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseOptionalVersionedTextDocumentIdentifier(
+          obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentEdit');
       return false;
@@ -38667,45 +29522,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('language');
-      try {
-        if (!obj.containsKey('language')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final language = obj['language'];
-        if (language == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (language is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'language',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('pattern');
-      try {
-        final pattern = obj['pattern'];
-        if (pattern != null && pattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'pattern',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        final scheme = obj['scheme'];
-        if (scheme != null && scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'scheme',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentFilter1');
       return false;
@@ -38781,45 +29607,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('language');
-      try {
-        final language = obj['language'];
-        if (language != null && language is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'language',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('pattern');
-      try {
-        if (!obj.containsKey('pattern')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final pattern = obj['pattern'];
-        if (pattern == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (pattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'pattern',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        final scheme = obj['scheme'];
-        if (scheme != null && scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'scheme',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentFilter3');
       return false;
@@ -38895,45 +29692,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('language');
-      try {
-        final language = obj['language'];
-        if (language != null && language is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'language',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('pattern');
-      try {
-        final pattern = obj['pattern'];
-        if (pattern != null && pattern is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'pattern',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('scheme');
-      try {
-        if (!obj.containsKey('scheme')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final scheme = obj['scheme'];
-        if (scheme == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (scheme is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'scheme',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentFilterWithScheme');
       return false;
@@ -38997,25 +29765,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentIdentifier');
       return false;
@@ -39091,79 +29842,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('languageId');
-      try {
-        if (!obj.containsKey('languageId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final languageId = obj['languageId'];
-        if (languageId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (languageId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'languageId',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('text');
-      try {
-        if (!obj.containsKey('text')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final text = obj['text'];
-        if (text == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (text is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'text',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        if (!obj.containsKey('version')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final version = obj['version'];
-        if (version == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentItem');
       return false;
@@ -39274,43 +29966,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentPositionParams');
       return false;
@@ -39466,25 +30127,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true);
     } else {
       reporter.reportError('must be of type TextDocumentRegistrationOptions');
       return false;
@@ -39516,9 +30161,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Automatic after a delay.
   static const AfterDelay = TextDocumentSaveReason(2);
@@ -39592,35 +30235,13 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('includeText');
-      try {
-        final includeText = obj['includeText'];
-        if (includeText != null && includeText is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'includeText',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type TextDocumentSaveRegistrationOptions');
@@ -39714,47 +30335,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('didSave');
-      try {
-        final didSave = obj['didSave'];
-        if (didSave != null && didSave is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'didSave',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willSave');
-      try {
-        final willSave = obj['willSave'];
-        if (willSave != null && willSave is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'willSave',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willSaveWaitUntil');
-      try {
-        final willSaveWaitUntil = obj['willSaveWaitUntil'];
-        if (willSaveWaitUntil != null && willSaveWaitUntil is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'willSaveWaitUntil',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type TextDocumentSyncClientCapabilities');
@@ -39792,9 +30386,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Documents are synced by always sending the full content of the document.
   static const Full = TextDocumentSyncKind(1);
@@ -39900,60 +30492,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('change');
-      try {
-        final change = obj['change'];
-        if (change != null &&
-            !TextDocumentSyncKind.canParse(change, reporter)) {
-          reporter.reportError('must be of type TextDocumentSyncKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentSyncKind(obj, reporter, 'change',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('openClose');
-      try {
-        final openClose = obj['openClose'];
-        if (openClose != null && openClose is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'openClose',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('save');
-      try {
-        final save = obj['save'];
-        if (save != null &&
-            save is! bool &&
-            !SaveOptions.canParse(save, reporter)) {
-          reporter.reportError('must be of type Either2<bool, SaveOptions>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolSaveOptions(obj, reporter, 'save',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willSave');
-      try {
-        final willSave = obj['willSave'];
-        if (willSave != null && willSave is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'willSave',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('willSaveWaitUntil');
-      try {
-        final willSaveWaitUntil = obj['willSaveWaitUntil'];
-        if (willSaveWaitUntil != null && willSaveWaitUntil is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'willSaveWaitUntil',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextDocumentSyncOptions');
       return false;
@@ -40029,43 +30585,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('newText');
-      try {
-        if (!obj.containsKey('newText')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final newText = obj['newText'];
-        if (newText == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (newText is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'newText',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TextEdit');
       return false;
@@ -40096,10 +30621,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
-
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
   static const Relative = TokenFormat('relative');
 
   @override
@@ -40122,9 +30644,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// Trace messages only.
   static const Messages = TraceValues('messages');
@@ -40195,27 +30715,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('linkSupport');
-      try {
-        final linkSupport = obj['linkSupport'];
-        if (linkSupport != null && linkSupport is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'linkSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeDefinitionClientCapabilities');
       return false;
@@ -40274,17 +30779,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeDefinitionOptions');
       return false;
@@ -40376,67 +30872,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeDefinitionParams');
       return false;
@@ -40525,45 +30974,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeDefinitionRegistrationOptions');
       return false;
@@ -40629,17 +31050,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeHierarchyClientCapabilities');
       return false;
@@ -40760,119 +31172,32 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('detail');
-      try {
-        final detail = obj['detail'];
-        if (detail != null && detail is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'detail',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SymbolKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type SymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSymbolKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('range');
-      try {
-        if (!obj.containsKey('range')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final range = obj['range'];
-        if (range == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(range, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'range',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('selectionRange');
-      try {
-        if (!obj.containsKey('selectionRange')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final selectionRange = obj['selectionRange'];
-        if (selectionRange == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Range.canParse(selectionRange, reporter)) {
-          reporter.reportError('must be of type Range');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseRange(obj, reporter, 'selectionRange',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListSymbolTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeHierarchyItem');
       return false;
@@ -40946,17 +31271,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeHierarchyOptions');
       return false;
@@ -41033,55 +31349,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('position');
-      try {
-        if (!obj.containsKey('position')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final position = obj['position'];
-        if (position == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Position.canParse(position, reporter)) {
-          reporter.reportError('must be of type Position');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParsePosition(obj, reporter, 'position',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeHierarchyPrepareParams');
       return false;
@@ -41171,45 +31448,17 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('documentSelector');
-      try {
-        if (!obj.containsKey('documentSelector')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final documentSelector = obj['documentSelector'];
-        if (documentSelector != null &&
-            (documentSelector is! List<Object?> ||
-                documentSelector.any((item) =>
-                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<TextDocumentFilterWithScheme>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListTextDocumentFilterWithScheme(
+          obj, reporter, 'documentSelector',
+          allowsUndefined: false, allowsNull: true)) {
+        return false;
       }
-      reporter.push('id');
-      try {
-        final id = obj['id'];
-        if (id != null && id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeHierarchyRegistrationOptions');
       return false;
@@ -41298,49 +31547,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('item');
-      try {
-        if (!obj.containsKey('item')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final item = obj['item'];
-        if (item == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TypeHierarchyItem.canParse(item, reporter)) {
-          reporter.reportError('must be of type TypeHierarchyItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTypeHierarchyItem(obj, reporter, 'item',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeHierarchySubtypesParams');
       return false;
@@ -41425,49 +31641,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('item');
-      try {
-        if (!obj.containsKey('item')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final item = obj['item'];
-        if (item == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TypeHierarchyItem.canParse(item, reporter)) {
-          reporter.reportError('must be of type TypeHierarchyItem');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTypeHierarchyItem(obj, reporter, 'item',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type TypeHierarchySupertypesParams');
       return false;
@@ -41549,43 +31732,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'unchanged') {
-          reporter.reportError('must be the literal \'unchanged\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'unchanged')) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        if (!obj.containsKey('resultId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final resultId = obj['resultId'];
-        if (resultId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'resultId',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type UnchangedDocumentDiagnosticReport');
       return false;
@@ -41619,9 +31771,7 @@
 
   final String _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is String;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
 
   /// The moniker is only unique inside a document
   static const document = UniquenessLevel('document');
@@ -41691,43 +31841,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('id');
-      try {
-        if (!obj.containsKey('id')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final id = obj['id'];
-        if (id == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (id is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'id',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('method');
-      try {
-        if (!obj.containsKey('method')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final method = obj['method'];
-        if (method == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (method is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'method',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type Unregistration');
       return false;
@@ -41783,27 +31902,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('unregisterations');
-      try {
-        if (!obj.containsKey('unregisterations')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final unregisterations = obj['unregisterations'];
-        if (unregisterations == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (unregisterations is! List<Object?> ||
-            unregisterations
-                .any((item) => !Unregistration.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Unregistration>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListUnregistration(obj, reporter, 'unregisterations',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type UnregistrationParams');
       return false;
@@ -41866,43 +31966,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        if (!obj.containsKey('version')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final version = obj['version'];
-        if (version == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type VersionedNotebookDocumentIdentifier');
@@ -41968,43 +32037,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        if (!obj.containsKey('version')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final version = obj['version'];
-        if (version == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type VersionedTextDocumentIdentifier');
       return false;
@@ -42035,9 +32073,7 @@
 
   final int _value;
 
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is int;
-  }
+  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
 
   /// Interested in change events
   static const Change = WatchKind(2);
@@ -42101,43 +32137,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('reason');
-      try {
-        if (!obj.containsKey('reason')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final reason = obj['reason'];
-        if (reason == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentSaveReason.canParse(reason, reporter)) {
-          reporter.reportError('must be of type TextDocumentSaveReason');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseTextDocumentSaveReason(obj, reporter, 'reason',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('textDocument');
-      try {
-        if (!obj.containsKey('textDocument')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final textDocument = obj['textDocument'];
-        if (textDocument == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
-          reporter.reportError('must be of type TextDocumentIdentifier');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WillSaveTextDocumentParams');
       return false;
@@ -42230,42 +32235,18 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('showDocument');
-      try {
-        final showDocument = obj['showDocument'];
-        if (showDocument != null &&
-            !ShowDocumentClientCapabilities.canParse(showDocument, reporter)) {
-          reporter
-              .reportError('must be of type ShowDocumentClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseShowDocumentClientCapabilities(
+          obj, reporter, 'showDocument',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('showMessage');
-      try {
-        final showMessage = obj['showMessage'];
-        if (showMessage != null &&
-            !ShowMessageRequestClientCapabilities.canParse(
-                showMessage, reporter)) {
-          reporter.reportError(
-              'must be of type ShowMessageRequestClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseShowMessageRequestClientCapabilities(
+          obj, reporter, 'showMessage',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WindowClientCapabilities');
       return false;
@@ -42375,73 +32356,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cancellable');
-      try {
-        final cancellable = obj['cancellable'];
-        if (cancellable != null && cancellable is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'cancellable',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'begin') {
-          reporter.reportError('must be the literal \'begin\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'begin')) {
+        return false;
       }
-      reporter.push('message');
-      try {
-        final message = obj['message'];
-        if (message != null && message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('percentage');
-      try {
-        final percentage = obj['percentage'];
-        if (percentage != null && percentage is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInt(obj, reporter, 'percentage',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('title');
-      try {
-        if (!obj.containsKey('title')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final title = obj['title'];
-        if (title == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (title is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'title',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkDoneProgressBegin');
       return false;
@@ -42501,25 +32433,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('token');
-      try {
-        if (!obj.containsKey('token')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final token = obj['token'];
-        if (token == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (token is! int && token is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'token',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkDoneProgressCancelParams');
       return false;
@@ -42569,25 +32484,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('token');
-      try {
-        if (!obj.containsKey('token')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final token = obj['token'];
-        if (token == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (token is! int && token is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'token',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkDoneProgressCreateParams');
       return false;
@@ -42651,35 +32549,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'end') {
-          reporter.reportError('must be the literal \'end\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'end')) {
+        return false;
       }
-      reporter.push('message');
-      try {
-        final message = obj['message'];
-        if (message != null && message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'message',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkDoneProgressEnd');
       return false;
@@ -42821,17 +32696,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkDoneProgressOptions');
       return false;
@@ -43001,19 +32867,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkDoneProgressParams');
       return false;
@@ -43107,55 +32962,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('cancellable');
-      try {
-        final cancellable = obj['cancellable'];
-        if (cancellable != null && cancellable is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'cancellable',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'report') {
-          reporter.reportError('must be the literal \'report\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'report')) {
+        return false;
       }
-      reporter.push('message');
-      try {
-        final message = obj['message'];
-        if (message != null && message is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'message',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('percentage');
-      try {
-        final percentage = obj['percentage'];
-        if (percentage != null && percentage is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'percentage',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkDoneProgressReport');
       return false;
@@ -43402,178 +33222,70 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('applyEdit');
-      try {
-        final applyEdit = obj['applyEdit'];
-        if (applyEdit != null && applyEdit is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'applyEdit',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('codeLens');
-      try {
-        final codeLens = obj['codeLens'];
-        if (codeLens != null &&
-            !CodeLensWorkspaceClientCapabilities.canParse(codeLens, reporter)) {
-          reporter.reportError(
-              'must be of type CodeLensWorkspaceClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseCodeLensWorkspaceClientCapabilities(
+          obj, reporter, 'codeLens',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('configuration');
-      try {
-        final configuration = obj['configuration'];
-        if (configuration != null && configuration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'configuration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('diagnostics');
-      try {
-        final diagnostics = obj['diagnostics'];
-        if (diagnostics != null &&
-            !DiagnosticWorkspaceClientCapabilities.canParse(
-                diagnostics, reporter)) {
-          reporter.reportError(
-              'must be of type DiagnosticWorkspaceClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDiagnosticWorkspaceClientCapabilities(
+          obj, reporter, 'diagnostics',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didChangeConfiguration');
-      try {
-        final didChangeConfiguration = obj['didChangeConfiguration'];
-        if (didChangeConfiguration != null &&
-            !DidChangeConfigurationClientCapabilities.canParse(
-                didChangeConfiguration, reporter)) {
-          reporter.reportError(
-              'must be of type DidChangeConfigurationClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDidChangeConfigurationClientCapabilities(
+          obj, reporter, 'didChangeConfiguration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('didChangeWatchedFiles');
-      try {
-        final didChangeWatchedFiles = obj['didChangeWatchedFiles'];
-        if (didChangeWatchedFiles != null &&
-            !DidChangeWatchedFilesClientCapabilities.canParse(
-                didChangeWatchedFiles, reporter)) {
-          reporter.reportError(
-              'must be of type DidChangeWatchedFilesClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseDidChangeWatchedFilesClientCapabilities(
+          obj, reporter, 'didChangeWatchedFiles',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('executeCommand');
-      try {
-        final executeCommand = obj['executeCommand'];
-        if (executeCommand != null &&
-            !ExecuteCommandClientCapabilities.canParse(
-                executeCommand, reporter)) {
-          reporter
-              .reportError('must be of type ExecuteCommandClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseExecuteCommandClientCapabilities(
+          obj, reporter, 'executeCommand',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('fileOperations');
-      try {
-        final fileOperations = obj['fileOperations'];
-        if (fileOperations != null &&
-            !FileOperationClientCapabilities.canParse(
-                fileOperations, reporter)) {
-          reporter
-              .reportError('must be of type FileOperationClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFileOperationClientCapabilities(
+          obj, reporter, 'fileOperations',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('inlayHint');
-      try {
-        final inlayHint = obj['inlayHint'];
-        if (inlayHint != null &&
-            !InlayHintWorkspaceClientCapabilities.canParse(
-                inlayHint, reporter)) {
-          reporter.reportError(
-              'must be of type InlayHintWorkspaceClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInlayHintWorkspaceClientCapabilities(
+          obj, reporter, 'inlayHint',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('inlineValue');
-      try {
-        final inlineValue = obj['inlineValue'];
-        if (inlineValue != null &&
-            !InlineValueWorkspaceClientCapabilities.canParse(
-                inlineValue, reporter)) {
-          reporter.reportError(
-              'must be of type InlineValueWorkspaceClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseInlineValueWorkspaceClientCapabilities(
+          obj, reporter, 'inlineValue',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('semanticTokens');
-      try {
-        final semanticTokens = obj['semanticTokens'];
-        if (semanticTokens != null &&
-            !SemanticTokensWorkspaceClientCapabilities.canParse(
-                semanticTokens, reporter)) {
-          reporter.reportError(
-              'must be of type SemanticTokensWorkspaceClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSemanticTokensWorkspaceClientCapabilities(
+          obj, reporter, 'semanticTokens',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('symbol');
-      try {
-        final symbol = obj['symbol'];
-        if (symbol != null &&
-            !WorkspaceSymbolClientCapabilities.canParse(symbol, reporter)) {
-          reporter
-              .reportError('must be of type WorkspaceSymbolClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWorkspaceSymbolClientCapabilities(obj, reporter, 'symbol',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspaceEdit');
-      try {
-        final workspaceEdit = obj['workspaceEdit'];
-        if (workspaceEdit != null &&
-            !WorkspaceEditClientCapabilities.canParse(
-                workspaceEdit, reporter)) {
-          reporter
-              .reportError('must be of type WorkspaceEditClientCapabilities');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWorkspaceEditClientCapabilities(
+          obj, reporter, 'workspaceEdit',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workspaceFolders');
-      try {
-        final workspaceFolders = obj['workspaceFolders'];
-        if (workspaceFolders != null && workspaceFolders is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workspaceFolders',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceClientCapabilities');
       return false;
@@ -43694,61 +33406,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('identifier');
-      try {
-        final identifier = obj['identifier'];
-        if (identifier != null && identifier is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'identifier',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('previousResultIds');
-      try {
-        if (!obj.containsKey('previousResultIds')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final previousResultIds = obj['previousResultIds'];
-        if (previousResultIds == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (previousResultIds is! List<Object?> ||
-            previousResultIds
-                .any((item) => !PreviousResultId.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<PreviousResultId>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListPreviousResultId(obj, reporter, 'previousResultIds',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceDiagnosticParams');
       return false;
@@ -43815,31 +33486,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('items');
-      try {
-        if (!obj.containsKey('items')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final items = obj['items'];
-        if (items == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (items is! List<Object?> ||
-            items.any((item) =>
-                !WorkspaceFullDocumentDiagnosticReport.canParse(
-                    item, reporter) &&
-                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
-                    item, reporter))) {
-          reporter.reportError(
-              'must be of type List<Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
+          obj, reporter, 'items',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceDiagnosticReport');
       return false;
@@ -43907,31 +33556,9 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('items');
-      try {
-        if (!obj.containsKey('items')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final items = obj['items'];
-        if (items == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (items is! List<Object?> ||
-            items.any((item) =>
-                !WorkspaceFullDocumentDiagnosticReport.canParse(
-                    item, reporter) &&
-                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
-                    item, reporter))) {
-          reporter.reportError(
-              'must be of type List<Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
+          obj, reporter, 'items',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type WorkspaceDiagnosticReportPartialResult');
@@ -44058,56 +33685,18 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('changeAnnotations');
-      try {
-        final changeAnnotations = obj['changeAnnotations'];
-        if (changeAnnotations != null &&
-            (changeAnnotations is! Map ||
-                (changeAnnotations.keys.any((item) =>
-                    item is! String ||
-                    changeAnnotations.values.any((item) =>
-                        !ChangeAnnotation.canParse(item, reporter)))))) {
-          reporter.reportError('must be of type Map<String, ChangeAnnotation>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMapStringChangeAnnotation(
+          obj, reporter, 'changeAnnotations',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('changes');
-      try {
-        final changes = obj['changes'];
-        if (changes != null &&
-            (changes is! Map ||
-                (changes.keys.any((item) =>
-                    item is! String ||
-                    changes.values.any((item) =>
-                        item is! List<Object?> ||
-                        item.any(
-                            (item) => !TextEdit.canParse(item, reporter))))))) {
-          reporter.reportError('must be of type Map<String, List<TextEdit>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseMapStringListTextEdit(obj, reporter, 'changes',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentChanges');
-      try {
-        final documentChanges = obj['documentChanges'];
-        if (documentChanges != null &&
-            (documentChanges is! List<Object?> ||
-                documentChanges.any((item) =>
-                    !CreateFile.canParse(item, reporter) &&
-                    !DeleteFile.canParse(item, reporter) &&
-                    !RenameFile.canParse(item, reporter) &&
-                    !TextDocumentEdit.canParse(item, reporter)))) {
-          reporter.reportError(
-              'must be of type List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListCreateFileDeleteFileRenameFileTextDocumentEdit(
+          obj, reporter, 'documentChanges',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceEdit');
       return false;
@@ -44239,64 +33828,26 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('changeAnnotationSupport');
-      try {
-        final changeAnnotationSupport = obj['changeAnnotationSupport'];
-        if (changeAnnotationSupport != null &&
-            !WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse(
-                changeAnnotationSupport, reporter)) {
-          reporter.reportError(
-              'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWorkspaceEditClientCapabilitiesChangeAnnotationSupport(
+          obj, reporter, 'changeAnnotationSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('documentChanges');
-      try {
-        final documentChanges = obj['documentChanges'];
-        if (documentChanges != null && documentChanges is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'documentChanges',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('failureHandling');
-      try {
-        final failureHandling = obj['failureHandling'];
-        if (failureHandling != null &&
-            !FailureHandlingKind.canParse(failureHandling, reporter)) {
-          reporter.reportError('must be of type FailureHandlingKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseFailureHandlingKind(obj, reporter, 'failureHandling',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('normalizesLineEndings');
-      try {
-        final normalizesLineEndings = obj['normalizesLineEndings'];
-        if (normalizesLineEndings != null && normalizesLineEndings is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'normalizesLineEndings',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resourceOperations');
-      try {
-        final resourceOperations = obj['resourceOperations'];
-        if (resourceOperations != null &&
-            (resourceOperations is! List<Object?> ||
-                resourceOperations.any((item) =>
-                    !ResourceOperationKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<ResourceOperationKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListResourceOperationKind(
+          obj, reporter, 'resourceOperations',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceEditClientCapabilities');
       return false;
@@ -44363,17 +33914,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('groupsOnLabel');
-      try {
-        final groupsOnLabel = obj['groupsOnLabel'];
-        if (groupsOnLabel != null && groupsOnLabel is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'groupsOnLabel',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
@@ -44435,43 +33977,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceFolder');
       return false;
@@ -44538,45 +34049,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('added');
-      try {
-        if (!obj.containsKey('added')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final added = obj['added'];
-        if (added == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (added is! List<Object?> ||
-            added.any((item) => !WorkspaceFolder.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<WorkspaceFolder>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListWorkspaceFolder(obj, reporter, 'added',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('removed');
-      try {
-        if (!obj.containsKey('removed')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final removed = obj['removed'];
-        if (removed == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (removed is! List<Object?> ||
-            removed.any((item) => !WorkspaceFolder.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<WorkspaceFolder>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListWorkspaceFolder(obj, reporter, 'removed',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
       return false;
@@ -44652,29 +34130,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('changeNotifications');
-      try {
-        final changeNotifications = obj['changeNotifications'];
-        if (changeNotifications != null &&
-            changeNotifications is! bool &&
-            changeNotifications is! String) {
-          reporter.reportError('must be of type Either2<bool, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBoolString(obj, reporter, 'changeNotifications',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('supported');
-      try {
-        final supported = obj['supported'];
-        if (supported != null && supported is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'supported',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type WorkspaceFoldersServerCapabilities');
@@ -44779,86 +34240,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('items');
-      try {
-        if (!obj.containsKey('items')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final items = obj['items'];
-        if (items == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (items is! List<Object?> ||
-            items.any((item) => !Diagnostic.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<Diagnostic>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseListDiagnostic(obj, reporter, 'items',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'full') {
-          reporter.reportError('must be the literal \'full\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'full')) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        final resultId = obj['resultId'];
-        if (resultId != null && resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'resultId',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        if (!obj.containsKey('version')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final version = obj['version'];
-        if (version != null && version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: false, allowsNull: true);
     } else {
       reporter
           .reportError('must be of type WorkspaceFullDocumentDiagnosticReport');
@@ -44986,85 +34385,24 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('containerName');
-      try {
-        final containerName = obj['containerName'];
-        if (containerName != null && containerName is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'containerName',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!SymbolKind.canParse(kind, reporter)) {
-          reporter.reportError('must be of type SymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseSymbolKind(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('location');
-      try {
-        if (!obj.containsKey('location')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final location = obj['location'];
-        if (location == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!Location.canParse(location, reporter) &&
-            !WorkspaceSymbolLocation.canParse(location, reporter)) {
-          reporter.reportError(
-              'must be of type Either2<Location, WorkspaceSymbolLocation>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLocationWorkspaceSymbolLocation(obj, reporter, 'location',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('name');
-      try {
-        if (!obj.containsKey('name')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final name = obj['name'];
-        if (name == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (name is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'name',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tags');
-      try {
-        final tags = obj['tags'];
-        if (tags != null &&
-            (tags is! List<Object?> ||
-                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolTag(obj, reporter, 'tags',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceSymbol');
       return false;
@@ -45176,56 +34514,23 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('dynamicRegistration');
-      try {
-        final dynamicRegistration = obj['dynamicRegistration'];
-        if (dynamicRegistration != null && dynamicRegistration is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('resolveSupport');
-      try {
-        final resolveSupport = obj['resolveSupport'];
-        if (resolveSupport != null &&
-            !WorkspaceSymbolClientCapabilitiesResolveSupport.canParse(
-                resolveSupport, reporter)) {
-          reporter.reportError(
-              'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWorkspaceSymbolClientCapabilitiesResolveSupport(
+          obj, reporter, 'resolveSupport',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('symbolKind');
-      try {
-        final symbolKind = obj['symbolKind'];
-        if (symbolKind != null &&
-            !WorkspaceSymbolClientCapabilitiesSymbolKind.canParse(
-                symbolKind, reporter)) {
-          reporter.reportError(
-              'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseWorkspaceSymbolClientCapabilitiesSymbolKind(
+          obj, reporter, 'symbolKind',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('tagSupport');
-      try {
-        final tagSupport = obj['tagSupport'];
-        if (tagSupport != null &&
-            !WorkspaceSymbolClientCapabilitiesTagSupport.canParse(
-                tagSupport, reporter)) {
-          reporter.reportError(
-              'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseWorkspaceSymbolClientCapabilitiesTagSupport(
+          obj, reporter, 'tagSupport',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
       return false;
@@ -45286,26 +34591,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('properties');
-      try {
-        if (!obj.containsKey('properties')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final properties = obj['properties'];
-        if (properties == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (properties is! List<Object?> ||
-            properties.any((item) => item is! String)) {
-          reporter.reportError('must be of type List<String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListString(obj, reporter, 'properties',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
@@ -45366,19 +34653,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        final valueSet = obj['valueSet'];
-        if (valueSet != null &&
-            (valueSet is! List<Object?> ||
-                valueSet.any((item) => !SymbolKind.canParse(item, reporter)))) {
-          reporter.reportError('must be of type List<SymbolKind>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolKind(obj, reporter, 'valueSet',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
@@ -45433,26 +34709,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('valueSet');
-      try {
-        if (!obj.containsKey('valueSet')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final valueSet = obj['valueSet'];
-        if (valueSet == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (valueSet is! List<Object?> ||
-            valueSet.any((item) => !SymbolTag.canParse(item, reporter))) {
-          reporter.reportError('must be of type List<SymbolTag>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseListSymbolTag(obj, reporter, 'valueSet',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError(
           'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
@@ -45503,25 +34761,8 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceSymbolLocation');
       return false;
@@ -45590,27 +34831,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceSymbolOptions');
       return false;
@@ -45693,49 +34919,16 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('partialResultToken');
-      try {
-        final partialResultToken = obj['partialResultToken'];
-        if (partialResultToken != null &&
-            partialResultToken is! int &&
-            partialResultToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseIntString(obj, reporter, 'partialResultToken',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('query');
-      try {
-        if (!obj.containsKey('query')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final query = obj['query'];
-        if (query == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (query is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'query',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneToken');
-      try {
-        final workDoneToken = obj['workDoneToken'];
-        if (workDoneToken != null &&
-            workDoneToken is! int &&
-            workDoneToken is! String) {
-          reporter.reportError('must be of type Either2<int, String>');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseIntString(obj, reporter, 'workDoneToken',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter.reportError('must be of type WorkspaceSymbolParams');
       return false;
@@ -45809,27 +35002,12 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('resolveProvider');
-      try {
-        final resolveProvider = obj['resolveProvider'];
-        if (resolveProvider != null && resolveProvider is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseBool(obj, reporter, 'resolveProvider',
+          allowsUndefined: true, allowsNull: false)) {
+        return false;
       }
-      reporter.push('workDoneProgress');
-      try {
-        final workDoneProgress = obj['workDoneProgress'];
-        if (workDoneProgress != null && workDoneProgress is! bool) {
-          reporter.reportError('must be of type bool');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseBool(obj, reporter, 'workDoneProgress',
+          allowsUndefined: true, allowsNull: false);
     } else {
       reporter
           .reportError('must be of type WorkspaceSymbolRegistrationOptions');
@@ -45922,75 +35100,20 @@
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     if (obj is Map<String, Object?>) {
-      reporter.push('kind');
-      try {
-        if (!obj.containsKey('kind')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final kind = obj['kind'];
-        if (kind == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (kind != 'unchanged') {
-          reporter.reportError('must be the literal \'unchanged\'');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseLiteral(obj, reporter, 'kind',
+          allowsUndefined: false, allowsNull: false, literal: 'unchanged')) {
+        return false;
       }
-      reporter.push('resultId');
-      try {
-        if (!obj.containsKey('resultId')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final resultId = obj['resultId'];
-        if (resultId == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (resultId is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'resultId',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('uri');
-      try {
-        if (!obj.containsKey('uri')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final uri = obj['uri'];
-        if (uri == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (uri is! String) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
+      if (!_canParseString(obj, reporter, 'uri',
+          allowsUndefined: false, allowsNull: false)) {
+        return false;
       }
-      reporter.push('version');
-      try {
-        if (!obj.containsKey('version')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final version = obj['version'];
-        if (version != null && version is! int) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
+      return _canParseInt(obj, reporter, 'version',
+          allowsUndefined: false, allowsNull: true);
     } else {
       reporter.reportError(
           'must be of type WorkspaceUnchangedDocumentDiagnosticReport');
@@ -46020,6 +35143,6866 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+bool _canParseBool(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value is! bool) {
+      reporter.reportError('must be of type bool');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolCallHierarchyOptionsCallHierarchyRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !CallHierarchyOptions.canParse(value, reporter) &&
+            !CallHierarchyRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolCodeActionOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !CodeActionOptions.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<bool, CodeActionOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolDeclarationOptionsDeclarationRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !DeclarationOptions.canParse(value, reporter) &&
+            !DeclarationRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolDefinitionOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !DefinitionOptions.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<bool, DefinitionOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolDocumentColorOptionsDocumentColorRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !DocumentColorOptions.canParse(value, reporter) &&
+            !DocumentColorRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolDocumentFormattingOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !DocumentFormattingOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<bool, DocumentFormattingOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolDocumentHighlightOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !DocumentHighlightOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<bool, DocumentHighlightOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolDocumentRangeFormattingOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !DocumentRangeFormattingOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<bool, DocumentRangeFormattingOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolDocumentSymbolOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !DocumentSymbolOptions.canParse(value, reporter))) {
+      reporter
+          .reportError('must be of type Either2<bool, DocumentSymbolOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolFoldingRangeOptionsFoldingRangeRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !FoldingRangeOptions.canParse(value, reporter) &&
+            !FoldingRangeRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolHoverOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !HoverOptions.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<bool, HoverOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolImplementationOptionsImplementationRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !ImplementationOptions.canParse(value, reporter) &&
+            !ImplementationRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolInlayHintOptionsInlayHintRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !InlayHintOptions.canParse(value, reporter) &&
+            !InlayHintRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolInlineValueOptionsInlineValueRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !InlineValueOptions.canParse(value, reporter) &&
+            !InlineValueRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool
+    _canParseBoolLinkedEditingRangeOptionsLinkedEditingRangeRegistrationOptions(
+        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+        {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !LinkedEditingRangeOptions.canParse(value, reporter) &&
+            !LinkedEditingRangeRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolMonikerOptionsMonikerRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !MonikerOptions.canParse(value, reporter) &&
+            !MonikerRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, MonikerOptions, MonikerRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolReferenceOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !ReferenceOptions.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<bool, ReferenceOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolRenameOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !RenameOptions.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<bool, RenameOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolSaveOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !SaveOptions.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<bool, SaveOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolSelectionRangeOptionsSelectionRangeRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !SelectionRangeOptions.canParse(value, reporter) &&
+            !SelectionRangeRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolSemanticTokensClientCapabilitiesRequestsFull(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !SemanticTokensClientCapabilitiesRequestsFull.canParse(
+                value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolSemanticTokensClientCapabilitiesRequestsRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !SemanticTokensClientCapabilitiesRequestsRange.canParse(
+                value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolSemanticTokensOptionsFull(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !SemanticTokensOptionsFull.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<bool, SemanticTokensOptionsFull>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolSemanticTokensOptionsRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !SemanticTokensOptionsRange.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<bool, SemanticTokensOptionsRange>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolString(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && (value is! bool && value is! String)) {
+      reporter.reportError('must be of type Either2<bool, String>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolTypeDefinitionOptionsTypeDefinitionRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !TypeDefinitionOptions.canParse(value, reporter) &&
+            !TypeDefinitionRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolTypeHierarchyOptionsTypeHierarchyRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool &&
+            !TypeHierarchyOptions.canParse(value, reporter) &&
+            !TypeHierarchyRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseBoolWorkspaceSymbolOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! bool && !WorkspaceSymbolOptions.canParse(value, reporter))) {
+      reporter
+          .reportError('must be of type Either2<bool, WorkspaceSymbolOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCallHierarchyClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CallHierarchyClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type CallHierarchyClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCallHierarchyItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CallHierarchyItem.canParse(value, reporter)) {
+      reporter.reportError('must be of type CallHierarchyItem');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type ClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeActionClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionClientCapabilitiesCodeActionLiteralSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionClientCapabilitiesCodeActionLiteralSupport.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionClientCapabilitiesResolveSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionClientCapabilitiesResolveSupport.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type CodeActionClientCapabilitiesResolveSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionContext(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionContext.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeActionContext');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionDisabled(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionDisabled.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeActionDisabled');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeActionKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionLiteralSupportCodeActionKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionLiteralSupportCodeActionKind.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type CodeActionLiteralSupportCodeActionKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeActionTriggerKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeActionTriggerKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeActionTriggerKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeDescription(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeDescription.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeDescription');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeLensClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeLensClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeLensClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeLensOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeLensOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type CodeLensOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCodeLensWorkspaceClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CodeLensWorkspaceClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type CodeLensWorkspaceClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseColor(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Color.canParse(value, reporter)) {
+      reporter.reportError('must be of type Color');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCommand(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Command.canParse(value, reporter)) {
+      reporter.reportError('must be of type Command');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionClientCapabilitiesCompletionItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionClientCapabilitiesCompletionItem.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type CompletionClientCapabilitiesCompletionItem');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionClientCapabilitiesCompletionItemKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionClientCapabilitiesCompletionItemKind.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type CompletionClientCapabilitiesCompletionItemKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionClientCapabilitiesCompletionList(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionClientCapabilitiesCompletionList.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type CompletionClientCapabilitiesCompletionList');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionContext(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionContext.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionContext');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionItemEditRangeRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!CompletionItemEditRange.canParse(value, reporter) &&
+            !Range.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<CompletionItemEditRange, Range>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionItemInsertTextModeSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionItemInsertTextModeSupport.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type CompletionItemInsertTextModeSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionItemKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionItemKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionItemKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionItemLabelDetails(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionItemLabelDetails.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionItemLabelDetails');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionItemResolutionInfo(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionItemResolutionInfo.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionItemResolutionInfo');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionItemResolveSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionItemResolveSupport.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionItemResolveSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionItemTagSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionItemTagSupport.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionItemTagSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionListItemDefaults(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionListItemDefaults.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionListItemDefaults');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionOptionsCompletionItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionOptionsCompletionItem.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionOptionsCompletionItem');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCompletionTriggerKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CompletionTriggerKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type CompletionTriggerKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseCreateFileOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !CreateFileOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type CreateFileOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDeclarationClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DeclarationClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type DeclarationClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDefinitionClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DefinitionClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type DefinitionClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDeleteFileOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DeleteFileOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type DeleteFileOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDiagnosticClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DiagnosticClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type DiagnosticClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDiagnosticOptionsDiagnosticRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!DiagnosticOptions.canParse(value, reporter) &&
+            !DiagnosticRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<DiagnosticOptions, DiagnosticRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDiagnosticSeverity(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DiagnosticSeverity.canParse(value, reporter)) {
+      reporter.reportError('must be of type DiagnosticSeverity');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDiagnosticWorkspaceClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DiagnosticWorkspaceClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type DiagnosticWorkspaceClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDidChangeConfigurationClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DidChangeConfigurationClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type DidChangeConfigurationClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDidChangeWatchedFilesClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DidChangeWatchedFilesClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type DidChangeWatchedFilesClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentColorClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentColorClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type DocumentColorClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentFormattingClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentFormattingClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type DocumentFormattingClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentHighlightClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentHighlightClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type DocumentHighlightClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentHighlightKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentHighlightKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type DocumentHighlightKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentLinkClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentLinkClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type DocumentLinkClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentLinkOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentLinkOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type DocumentLinkOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentOnTypeFormattingClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentOnTypeFormattingClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type DocumentOnTypeFormattingClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentOnTypeFormattingOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentOnTypeFormattingOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type DocumentOnTypeFormattingOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentRangeFormattingClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentRangeFormattingClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type DocumentRangeFormattingClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentSymbolClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentSymbolClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type DocumentSymbolClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentSymbolClientCapabilitiesSymbolKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentSymbolClientCapabilitiesSymbolKind.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseDocumentSymbolClientCapabilitiesTagSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !DocumentSymbolClientCapabilitiesTagSupport.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type DocumentSymbolClientCapabilitiesTagSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseEither3String(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!NotebookDocumentFilter1.canParse(value, reporter) &&
+            !NotebookDocumentFilter2.canParse(value, reporter) &&
+            !NotebookDocumentFilter3.canParse(value, reporter) &&
+            value is! String)) {
+      reporter.reportError(
+          'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseExecuteCommandClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ExecuteCommandClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type ExecuteCommandClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseExecuteCommandOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ExecuteCommandOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type ExecuteCommandOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseExecutionSummary(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ExecutionSummary.canParse(value, reporter)) {
+      reporter.reportError('must be of type ExecutionSummary');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFailureHandlingKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FailureHandlingKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type FailureHandlingKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFileChangeType(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FileChangeType.canParse(value, reporter)) {
+      reporter.reportError('must be of type FileChangeType');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFileOperationClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FileOperationClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type FileOperationClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFileOperationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FileOperationOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type FileOperationOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFileOperationPattern(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FileOperationPattern.canParse(value, reporter)) {
+      reporter.reportError('must be of type FileOperationPattern');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFileOperationPatternKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FileOperationPatternKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type FileOperationPatternKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFileOperationPatternOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FileOperationPatternOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type FileOperationPatternOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFileOperationRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FileOperationRegistrationOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type FileOperationRegistrationOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFoldingRangeClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FoldingRangeClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type FoldingRangeClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFoldingRangeClientCapabilitiesFoldingRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FoldingRangeClientCapabilitiesFoldingRange.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type FoldingRangeClientCapabilitiesFoldingRange');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFoldingRangeClientCapabilitiesFoldingRangeKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FoldingRangeClientCapabilitiesFoldingRangeKind.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFoldingRangeKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FoldingRangeKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type FoldingRangeKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseFormattingOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !FormattingOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type FormattingOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseGeneralClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !GeneralClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type GeneralClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseGeneralClientCapabilitiesStaleRequestSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !GeneralClientCapabilitiesStaleRequestSupport.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type GeneralClientCapabilitiesStaleRequestSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseHoverClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !HoverClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type HoverClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseImplementationClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ImplementationClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type ImplementationClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInitializeParamsClientInfo(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InitializeParamsClientInfo.canParse(value, reporter)) {
+      reporter.reportError('must be of type InitializeParamsClientInfo');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInitializeResultServerInfo(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InitializeResultServerInfo.canParse(value, reporter)) {
+      reporter.reportError('must be of type InitializeResultServerInfo');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInlayHintClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InlayHintClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type InlayHintClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInlayHintClientCapabilitiesResolveSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InlayHintClientCapabilitiesResolveSupport.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type InlayHintClientCapabilitiesResolveSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInlayHintKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InlayHintKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type InlayHintKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInlayHintWorkspaceClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InlayHintWorkspaceClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type InlayHintWorkspaceClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInlineValueClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InlineValueClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type InlineValueClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInlineValueContext(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InlineValueContext.canParse(value, reporter)) {
+      reporter.reportError('must be of type InlineValueContext');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInlineValueWorkspaceClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InlineValueWorkspaceClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type InlineValueWorkspaceClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInsertReplaceEditTextEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!InsertReplaceEdit.canParse(value, reporter) &&
+            !TextEdit.canParse(value, reporter))) {
+      reporter
+          .reportError('must be of type Either2<InsertReplaceEdit, TextEdit>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInsertTextFormat(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InsertTextFormat.canParse(value, reporter)) {
+      reporter.reportError('must be of type InsertTextFormat');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInsertTextMode(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !InsertTextMode.canParse(value, reporter)) {
+      reporter.reportError('must be of type InsertTextMode');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseInt(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value is! int) {
+      reporter.reportError('must be of type int');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseIntString(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && (value is! int && value is! String)) {
+      reporter.reportError('must be of type Either2<int, String>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseLinkedEditingRangeClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !LinkedEditingRangeClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type LinkedEditingRangeClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListAnnotatedTextEditSnippetTextEditTextEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !AnnotatedTextEdit.canParse(item, reporter) &&
+                !SnippetTextEdit.canParse(item, reporter) &&
+                !TextEdit.canParse(item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListCodeActionKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !CodeActionKind.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<CodeActionKind>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListCompletionItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !CompletionItem.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<CompletionItem>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListCompletionItemKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value
+                .any((item) => !CompletionItemKind.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<CompletionItemKind>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListCompletionItemTag(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !CompletionItemTag.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<CompletionItemTag>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListConfigurationItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !ConfigurationItem.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<ConfigurationItem>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListCreateFileDeleteFileRenameFileTextDocumentEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !CreateFile.canParse(item, reporter) &&
+                !DeleteFile.canParse(item, reporter) &&
+                !RenameFile.canParse(item, reporter) &&
+                !TextDocumentEdit.canParse(item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListDiagnostic(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !Diagnostic.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<Diagnostic>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListDiagnosticRelatedInformation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !DiagnosticRelatedInformation.canParse(item, reporter)))) {
+      reporter
+          .reportError('must be of type List<DiagnosticRelatedInformation>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListDiagnosticTag(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !DiagnosticTag.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<DiagnosticTag>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListDocumentSymbol(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !DocumentSymbol.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<DocumentSymbol>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFileCreate(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !FileCreate.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FileCreate>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFileDelete(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !FileDelete.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FileDelete>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFileEvent(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !FileEvent.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FileEvent>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFileOperationFilter(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any(
+                (item) => !FileOperationFilter.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FileOperationFilter>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFileRename(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !FileRename.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FileRename>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFileSystemWatcher(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !FileSystemWatcher.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FileSystemWatcher>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListFoldingRangeKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !FoldingRangeKind.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<FoldingRangeKind>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListInsertTextMode(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !InsertTextMode.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<InsertTextMode>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListInt(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> || value.any((item) => item is! int))) {
+      reporter.reportError('must be of type List<int>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListMarkupKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !MarkupKind.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<MarkupKind>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListMessageActionItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !MessageActionItem.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<MessageActionItem>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListNotebookCell(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !NotebookCell.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<NotebookCell>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListNotebookDocumentChangeEventCellsTextContent(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !NotebookDocumentChangeEventCellsTextContent.canParse(
+                    item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<NotebookDocumentChangeEventCellsTextContent>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListNotebookDocumentSyncOptionsNotebookSelector2Cells(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse(
+                    item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<NotebookDocumentSyncOptionsNotebookSelector2Cells>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListNotebookDocumentSyncOptionsNotebookSelectorCells(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !NotebookDocumentSyncOptionsNotebookSelectorCells.canParse(
+                    item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<NotebookDocumentSyncOptionsNotebookSelectorCells>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool
+    _canParseListNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
+        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+        {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
+                    item, reporter) &&
+                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
+                    item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListObject_(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> || value.any((item) => false))) {
+      reporter.reportError('must be of type List<Object?>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListParameterInformation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any(
+                (item) => !ParameterInformation.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<ParameterInformation>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListPosition(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !Position.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<Position>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListPositionEncodingKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any(
+                (item) => !PositionEncodingKind.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<PositionEncodingKind>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListPreviousResultId(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !PreviousResultId.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<PreviousResultId>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !Range.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<Range>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListRegistration(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !Registration.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<Registration>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListResourceOperationKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any(
+                (item) => !ResourceOperationKind.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<ResourceOperationKind>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListSemanticTokensEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value
+                .any((item) => !SemanticTokensEdit.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<SemanticTokensEdit>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListSignatureInformation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any(
+                (item) => !SignatureInformation.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<SignatureInformation>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListString(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> || value.any((item) => item is! String))) {
+      reporter.reportError('must be of type List<String>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListSymbolKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !SymbolKind.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<SymbolKind>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListSymbolTag(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !SymbolTag.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<SymbolTag>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool
+    _canParseListTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
+        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+        {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !TextDocumentContentChangeEvent1.canParse(item, reporter) &&
+                !TextDocumentContentChangeEvent2.canParse(item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListTextDocumentFilterWithScheme(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
+      reporter
+          .reportError('must be of type List<TextDocumentFilterWithScheme>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListTextDocumentIdentifier(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any(
+                (item) => !TextDocumentIdentifier.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<TextDocumentIdentifier>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListTextDocumentItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !TextDocumentItem.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<TextDocumentItem>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListTextEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !TextEdit.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<TextEdit>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListTokenFormat(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !TokenFormat.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<TokenFormat>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListUnregistration(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !Unregistration.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<Unregistration>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseListWorkspaceFolder(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) => !WorkspaceFolder.canParse(item, reporter)))) {
+      reporter.reportError('must be of type List<WorkspaceFolder>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool
+    _canParseListWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
+        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+        {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! List<Object?> ||
+            value.any((item) =>
+                !WorkspaceFullDocumentDiagnosticReport.canParse(
+                    item, reporter) &&
+                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
+                    item, reporter)))) {
+      reporter.reportError(
+          'must be of type List<Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseLiteral(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined,
+    required bool allowsNull,
+    required String literal}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value != literal) {
+      reporter.reportError("must be the literal '$literal'");
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseLiteralUnion(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined,
+    required bool allowsNull,
+    required Iterable<String> literals}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !literals.contains(value)) {
+      reporter.reportError(
+          "must be one of the ${literals.map((e) => "'$e'").join(', ')}");
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseLocation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Location.canParse(value, reporter)) {
+      reporter.reportError('must be of type Location');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseLocationWorkspaceSymbolLocation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!Location.canParse(value, reporter) &&
+            !WorkspaceSymbolLocation.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<Location, WorkspaceSymbolLocation>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMapStringChangeAnnotation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! Map ||
+            (value.keys.any((item) =>
+                item is! String ||
+                value.values.any(
+                    (item) => !ChangeAnnotation.canParse(item, reporter)))))) {
+      reporter.reportError('must be of type Map<String, ChangeAnnotation>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool
+    _canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
+        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+        {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! Map ||
+            (value.keys.any((item) =>
+                item is! String ||
+                value.values.any((item) =>
+                    !FullDocumentDiagnosticReport.canParse(item, reporter) &&
+                    !UnchangedDocumentDiagnosticReport.canParse(
+                        item, reporter)))))) {
+      reporter.reportError(
+          'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMapStringListTextEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! Map ||
+            (value.keys.any((item) =>
+                item is! String ||
+                value.values.any((item) =>
+                    item is! List<Object?> ||
+                    item.any(
+                        (item) => !TextEdit.canParse(item, reporter))))))) {
+      reporter.reportError('must be of type Map<String, List<TextEdit>>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMarkdownClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !MarkdownClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type MarkdownClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMarkupContentString(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!MarkupContent.canParse(value, reporter) && value is! String)) {
+      reporter.reportError('must be of type Either2<MarkupContent, String>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMarkupKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !MarkupKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type MarkupKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMessageType(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !MessageType.canParse(value, reporter)) {
+      reporter.reportError('must be of type MessageType');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMonikerClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !MonikerClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type MonikerClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseMonikerKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !MonikerKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type MonikerKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookCellArrayChange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookCellArrayChange.canParse(value, reporter)) {
+      reporter.reportError('must be of type NotebookCellArrayChange');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookCellKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookCellKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type NotebookCellKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookDocument(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookDocument.canParse(value, reporter)) {
+      reporter.reportError('must be of type NotebookDocument');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookDocumentChangeEvent(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookDocumentChangeEvent.canParse(value, reporter)) {
+      reporter.reportError('must be of type NotebookDocumentChangeEvent');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookDocumentChangeEventCells(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookDocumentChangeEventCells.canParse(value, reporter)) {
+      reporter.reportError('must be of type NotebookDocumentChangeEventCells');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookDocumentChangeEventCellsStructure(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookDocumentChangeEventCellsStructure.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type NotebookDocumentChangeEventCellsStructure');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookDocumentClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookDocumentClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type NotebookDocumentClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookDocumentIdentifier(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookDocumentIdentifier.canParse(value, reporter)) {
+      reporter.reportError('must be of type NotebookDocumentIdentifier');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNotebookDocumentSyncClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !NotebookDocumentSyncClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type NotebookDocumentSyncClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool
+    _canParseNotebookDocumentSyncOptionsNotebookDocumentSyncRegistrationOptions(
+        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+        {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!NotebookDocumentSyncOptions.canParse(value, reporter) &&
+            !NotebookDocumentSyncRegistrationOptions.canParse(
+                value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseNum(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value is! num) {
+      reporter.reportError('must be of type num');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseOptionalVersionedTextDocumentIdentifier(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !OptionalVersionedTextDocumentIdentifier.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type OptionalVersionedTextDocumentIdentifier');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParsePosition(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Position.canParse(value, reporter)) {
+      reporter.reportError('must be of type Position');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParsePositionEncodingKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !PositionEncodingKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type PositionEncodingKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParsePrepareSupportDefaultBehavior(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !PrepareSupportDefaultBehavior.canParse(value, reporter)) {
+      reporter.reportError('must be of type PrepareSupportDefaultBehavior');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParsePublishDiagnosticsClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !PublishDiagnosticsClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type PublishDiagnosticsClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParsePublishDiagnosticsClientCapabilitiesTagSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !PublishDiagnosticsClientCapabilitiesTagSupport.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !Range.canParse(value, reporter)) {
+      reporter.reportError('must be of type Range');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseReferenceClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ReferenceClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type ReferenceClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseReferenceContext(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ReferenceContext.canParse(value, reporter)) {
+      reporter.reportError('must be of type ReferenceContext');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseRegularExpressionsClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !RegularExpressionsClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type RegularExpressionsClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseRenameClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !RenameClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type RenameClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseRenameFileOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !RenameFileOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type RenameFileOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSelectionRange(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SelectionRange.canParse(value, reporter)) {
+      reporter.reportError('must be of type SelectionRange');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSelectionRangeClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SelectionRangeClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type SelectionRangeClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSemanticTokensClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SemanticTokensClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type SemanticTokensClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSemanticTokensClientCapabilitiesRequests(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SemanticTokensClientCapabilitiesRequests.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type SemanticTokensClientCapabilitiesRequests');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSemanticTokensLegend(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SemanticTokensLegend.canParse(value, reporter)) {
+      reporter.reportError('must be of type SemanticTokensLegend');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSemanticTokensOptionsSemanticTokensRegistrationOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!SemanticTokensOptions.canParse(value, reporter) &&
+            !SemanticTokensRegistrationOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSemanticTokensWorkspaceClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SemanticTokensWorkspaceClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type SemanticTokensWorkspaceClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseServerCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ServerCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type ServerCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseServerCapabilitiesWorkspace(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ServerCapabilitiesWorkspace.canParse(value, reporter)) {
+      reporter.reportError('must be of type ServerCapabilitiesWorkspace');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseShowDocumentClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ShowDocumentClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type ShowDocumentClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseShowMessageRequestClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ShowMessageRequestClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type ShowMessageRequestClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseShowMessageRequestClientCapabilitiesMessageActionItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !ShowMessageRequestClientCapabilitiesMessageActionItem.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSignatureHelp(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SignatureHelp.canParse(value, reporter)) {
+      reporter.reportError('must be of type SignatureHelp');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSignatureHelpClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SignatureHelpClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type SignatureHelpClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSignatureHelpClientCapabilitiesSignatureInformation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SignatureHelpClientCapabilitiesSignatureInformation.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSignatureHelpContext(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SignatureHelpContext.canParse(value, reporter)) {
+      reporter.reportError('must be of type SignatureHelpContext');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSignatureHelpOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SignatureHelpOptions.canParse(value, reporter)) {
+      reporter.reportError('must be of type SignatureHelpOptions');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSignatureHelpTriggerKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SignatureHelpTriggerKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type SignatureHelpTriggerKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSignatureInformationParameterInformation(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SignatureInformationParameterInformation.canParse(value, reporter)) {
+      reporter.reportError(
+          'must be of type SignatureInformationParameterInformation');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseString(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && value is! String) {
+      reporter.reportError('must be of type String');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseStringRelativePattern(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! String && !RelativePattern.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<String, RelativePattern>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseStringWorkspaceFolder(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (value is! String && !WorkspaceFolder.canParse(value, reporter))) {
+      reporter.reportError('must be of type Either2<String, WorkspaceFolder>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseSymbolKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !SymbolKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type SymbolKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextDocumentClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TextDocumentClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type TextDocumentClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextDocumentIdentifier(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TextDocumentIdentifier.canParse(value, reporter)) {
+      reporter.reportError('must be of type TextDocumentIdentifier');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextDocumentItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TextDocumentItem.canParse(value, reporter)) {
+      reporter.reportError('must be of type TextDocumentItem');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextDocumentSaveReason(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TextDocumentSaveReason.canParse(value, reporter)) {
+      reporter.reportError('must be of type TextDocumentSaveReason');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextDocumentSyncClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TextDocumentSyncClientCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type TextDocumentSyncClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextDocumentSyncKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TextDocumentSyncKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type TextDocumentSyncKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextDocumentSyncKindTextDocumentSyncOptions(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        (!TextDocumentSyncKind.canParse(value, reporter) &&
+            !TextDocumentSyncOptions.canParse(value, reporter))) {
+      reporter.reportError(
+          'must be of type Either2<TextDocumentSyncKind, TextDocumentSyncOptions>');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTextEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !TextEdit.canParse(value, reporter)) {
+      reporter.reportError('must be of type TextEdit');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTraceValues(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TraceValues.canParse(value, reporter)) {
+      reporter.reportError('must be of type TraceValues');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTypeDefinitionClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TypeDefinitionClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type TypeDefinitionClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTypeHierarchyClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TypeHierarchyClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type TypeHierarchyClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseTypeHierarchyItem(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !TypeHierarchyItem.canParse(value, reporter)) {
+      reporter.reportError('must be of type TypeHierarchyItem');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseUniquenessLevel(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !UniquenessLevel.canParse(value, reporter)) {
+      reporter.reportError('must be of type UniquenessLevel');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseVersionedNotebookDocumentIdentifier(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !VersionedNotebookDocumentIdentifier.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type VersionedNotebookDocumentIdentifier');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseVersionedTextDocumentIdentifier(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !VersionedTextDocumentIdentifier.canParse(value, reporter)) {
+      reporter.reportError('must be of type VersionedTextDocumentIdentifier');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWatchKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) && !WatchKind.canParse(value, reporter)) {
+      reporter.reportError('must be of type WatchKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWindowClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WindowClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type WindowClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type WorkspaceClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceEdit(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceEdit.canParse(value, reporter)) {
+      reporter.reportError('must be of type WorkspaceEdit');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceEditClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceEditClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type WorkspaceEditClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceEditClientCapabilitiesChangeAnnotationSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceFoldersChangeEvent(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceFoldersChangeEvent.canParse(value, reporter)) {
+      reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceFoldersServerCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceFoldersServerCapabilities.canParse(value, reporter)) {
+      reporter
+          .reportError('must be of type WorkspaceFoldersServerCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceSymbolClientCapabilities(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceSymbolClientCapabilities.canParse(value, reporter)) {
+      reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceSymbolClientCapabilitiesResolveSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceSymbolClientCapabilitiesResolveSupport.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceSymbolClientCapabilitiesSymbolKind(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceSymbolClientCapabilitiesSymbolKind.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
+bool _canParseWorkspaceSymbolClientCapabilitiesTagSupport(
+    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
+    {required bool allowsUndefined, required bool allowsNull}) {
+  reporter.push(fieldName);
+  try {
+    if (!allowsUndefined && !map.containsKey(fieldName)) {
+      reporter.reportError('must not be undefined');
+      return false;
+    }
+    final value = map[fieldName];
+    final nullCheck = allowsNull || allowsUndefined;
+    if (!nullCheck && value == null) {
+      reporter.reportError('must not be null');
+      return false;
+    }
+    if ((!nullCheck || value != null) &&
+        !WorkspaceSymbolClientCapabilitiesTagSupport.canParse(
+            value, reporter)) {
+      reporter.reportError(
+          'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
+      return false;
+    }
+  } finally {
+    reporter.pop();
+  }
+  return true;
+}
+
 Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>
     _eitherAnnotatedTextEditSnippetTextEditTextEdit(Object? value) {
   return AnnotatedTextEdit.canParse(value, nullLspJsonReporter)
@@ -46413,7 +42396,8 @@
           : throw '$value was not one of (int, String)';
 }
 
-Either2<List<InlayHintLabelPart>, String> _eitherListString(Object? value) {
+Either2<List<InlayHintLabelPart>, String> _eitherListInlayHintLabelPartString(
+    Object? value) {
   return value is List<Object?> &&
           value.every(
               (item) => InlayHintLabelPart.canParse(item, nullLspJsonReporter))
diff --git a/pkg/analysis_server/lib/src/analytics/analytics_manager.dart b/pkg/analysis_server/lib/src/analytics/analytics_manager.dart
index ab1a1486..f02612d 100644
--- a/pkg/analysis_server/lib/src/analytics/analytics_manager.dart
+++ b/pkg/analysis_server/lib/src/analytics/analytics_manager.dart
@@ -34,6 +34,9 @@
       required DateTime startTime,
       required DateTime endTime}) {}
 
+  /// Record the parameters passed on initialize.
+  void initialize(InitializeParams params);
+
   /// Record the number of [openWorkspacePaths].
   void initialized({required List<String> openWorkspacePaths});
 
diff --git a/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart b/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
index 092440d..2b5f502 100644
--- a/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
+++ b/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/protocol/protocol_constants.dart';
 import 'package:analysis_server/src/analytics/analytics_manager.dart';
 import 'package:analysis_server/src/analytics/percentile_calculator.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:telemetry/telemetry.dart';
@@ -71,6 +72,21 @@
   }
 
   @override
+  void initialize(InitializeParams params) {
+    var options = LspInitializationOptions(params.initializationOptions);
+    var paramNames = <String>[
+      if (options.closingLabels) 'closingLabels',
+      if (options.flutterOutline) 'flutterOutline',
+      if (options.onlyAnalyzeProjectsWithOpenFiles)
+        'onlyAnalyzeProjectsWithOpenFiles',
+      if (options.outline) 'outline',
+      if (options.suggestFromUnimportedLibraries)
+        'suggestFromUnimportedLibraries',
+    ];
+    _sessionData?.initializeParams = paramNames.join(',');
+  }
+
+  @override
   void initialized({required List<String> openWorkspacePaths}) {
     var requestData = _getRequestData(Method.initialized.toString());
     requestData.addValue('openWorkspacePaths', openWorkspacePaths.length);
@@ -154,7 +170,7 @@
       required String sdkVersion}) {
     _sessionData = _SessionData(
         startTime: time,
-        commandLineArguments: arguments.join(' '),
+        commandLineArguments: arguments.join(','),
         clientId: clientId,
         clientVersion: clientVersion ?? '',
         sdkVersion: sdkVersion);
@@ -234,6 +250,7 @@
     var duration = endTime - sessionData.startTime.millisecondsSinceEpoch;
     analytics.sendEvent('language_server', 'session', parameters: {
       'flags': sessionData.commandLineArguments,
+      'parameters': sessionData.initializeParams,
       'clientId': sessionData.clientId,
       'clientVersion': sessionData.clientVersion,
       'sdkVersion': sessionData.sdkVersion,
@@ -374,6 +391,9 @@
   /// The command-line arguments passed to the server on startup.
   final String commandLineArguments;
 
+  /// The parameters passed on initialize.
+  String initializeParams = '';
+
   /// The name of the client that started the server.
   final String clientId;
 
diff --git a/pkg/analysis_server/lib/src/analytics/noop_analytics_manager.dart b/pkg/analysis_server/lib/src/analytics/noop_analytics_manager.dart
index bcf2759..3f6c283 100644
--- a/pkg/analysis_server/lib/src/analytics/noop_analytics_manager.dart
+++ b/pkg/analysis_server/lib/src/analytics/noop_analytics_manager.dart
@@ -25,6 +25,9 @@
       required DateTime endTime}) {}
 
   @override
+  void initialize(InitializeParams params) {}
+
+  @override
   void initialized({required List<String> openWorkspacePaths}) {}
 
   @override
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
index 131daee..9efd825 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -22,6 +22,8 @@
   @override
   ErrorOr<InitializeResult> handle(
       InitializeParams params, MessageInfo message, CancellationToken token) {
+    server.analyticsManager.initialize(params);
+
     server.handleClientConnection(
       params.capabilities,
       params.initializationOptions,
diff --git a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
index 7d0ab6c..bd15489 100644
--- a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
@@ -150,8 +150,9 @@
 
     var dartBinary = join(dartSdkPath, 'bin', 'dart');
 
-    // Prevent flow analysis from marking code below as being dead.
-    const useSnapshot = 1 > 0;
+    // Setting the `TEST_SERVER_SNAPSHOT` env var to 'false' will disable the
+    // snapshot and run from source.
+    var useSnapshot = Platform.environment['TEST_SERVER_SNAPSHOT'] != 'false';
     String serverPath;
 
     if (useSnapshot) {
diff --git a/pkg/analysis_server/test/integration/support/integration_tests.dart b/pkg/analysis_server/test/integration/support/integration_tests.dart
index 1c692e9..8b8624c 100644
--- a/pkg/analysis_server/test/integration/support/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/support/integration_tests.dart
@@ -622,8 +622,9 @@
 
     var dartBinary = path.join(dartSdkPath, 'bin', 'dart');
 
-    // Prevent flow analysis from marking code below as being dead.
-    const useSnapshot = 1 > 0;
+    // Setting the `TEST_SERVER_SNAPSHOT` env var to 'false' will disable the
+    // snapshot and run from source.
+    var useSnapshot = Platform.environment['TEST_SERVER_SNAPSHOT'] != 'false';
     String serverPath;
 
     if (useSnapshot) {
diff --git a/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart b/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart
index 905c990..3542489 100644
--- a/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart
+++ b/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart
@@ -156,6 +156,25 @@
     ]);
   }
 
+  void test_server_request_initialize() {
+    _defaultStartup();
+    var params = InitializeParams(
+        capabilities: ClientCapabilities(),
+        initializationOptions: {
+          'closingLabels': true,
+          'notAnOption': true,
+          'onlyAnalyzeProjectsWithOpenFiles': true,
+        });
+    manager.initialize(params);
+    manager.shutdown();
+    analytics.assertEvents([
+      _ExpectedEvent.session(parameters: {
+        'parameters':
+            'closingLabels,onlyAnalyzeProjectsWithOpenFiles,suggestFromUnimportedLibraries',
+      }),
+    ]);
+  }
+
   void test_server_request_initialized() {
     _defaultStartup();
     var params = InitializedParams();
@@ -215,7 +234,7 @@
     manager.shutdown();
     analytics.assertEvents([
       _ExpectedEvent.session(parameters: {
-        'flags': arguments.join(' '),
+        'flags': arguments.join(','),
         'clientId': clientId,
         'clientVersion': '',
         'sdkVersion': sdkVersion,
@@ -254,7 +273,7 @@
     manager.shutdown();
     analytics.assertEvents([
       _ExpectedEvent.session(parameters: {
-        'flags': arguments.join(' '),
+        'flags': arguments.join(','),
         'clientId': clientId,
         'clientVersion': clientVersion,
         '': isNull,
diff --git a/pkg/analysis_server/test/src/cider/cider_service.dart b/pkg/analysis_server/test/src/cider/cider_service.dart
index b5d3b6f..5fb6ccc 100644
--- a/pkg/analysis_server/test/src/cider/cider_service.dart
+++ b/pkg/analysis_server/test/src/cider/cider_service.dart
@@ -4,8 +4,8 @@
 
 import 'dart:convert';
 
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
 import 'package:analyzer/src/dart/micro/resolve_file.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
@@ -43,7 +43,7 @@
       getFileDigest: (String path) => _getDigest(path),
       prefetchFiles: null,
       workspace: workspace,
-      byteStore: MemoryCiderByteStore(),
+      byteStore: MemoryByteStore(),
     );
     fileResolver.testView = FileResolverTestView();
   }
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index 7617762..5f8b54c 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -11,12 +11,13 @@
 import 'meta_model.dart';
 
 final formatter = DartFormatter();
-Map<String, Interface> _interfaces = {};
 
+final _canParseFunctions = SplayTreeMap<String, String>();
+Map<String, Interface> _interfaces = {};
 Map<String, LspEnum> _namespaces = {};
 Map<String, List<String>> _subtypes = {};
 Map<String, TypeAlias> _typeAliases = {};
-var _unionFunctions = SplayTreeMap<String, String>();
+final _unionFunctions = SplayTreeMap<String, String>();
 
 /// Whether our enum class allows any value (eg. should always return true
 /// from canParse() for the correct type). This is to allow us to have some
@@ -39,9 +40,13 @@
 }
 
 String generateDartForTypes(List<LspEntity> types) {
+  _canParseFunctions.clear();
   _unionFunctions.clear();
   final buffer = IndentableStringBuffer();
   _getSortedUnique(types).forEach((t) => _writeType(buffer, t));
+  for (var function in _canParseFunctions.values) {
+    buffer.writeln(function);
+  }
   for (var function in _unionFunctions.values) {
     buffer.writeln(function);
   }
@@ -179,9 +184,9 @@
   type = resolveTypeAlias(type);
 
   if (type is LiteralType) {
-    return 'must be the literal ${type.valueAsLiteral}';
+    return "must be the literal '\$literal'";
   } else if (type is LiteralUnionType) {
-    return 'must be one of the literals ${type.literalTypes.map((t) => t.valueAsLiteral).join(', ')}';
+    return "must be one of the \${literals.map((e) => \"'\$e'\").join(', ')}";
   } else {
     return 'must be of type ${type.dartTypeWithTypeArgs}';
   }
@@ -229,6 +234,28 @@
   return map[identifier] ?? identifier;
 }
 
+/// Returns the name of the possibly enclosed types,
+/// to be used as a unique name for that type.
+String _memberNameForType(TypeBase type) {
+  if (type is LiteralType) {
+    return 'Literal';
+  }
+  if (type is LiteralUnionType) {
+    return 'LiteralUnion';
+  }
+  if (type is TypeReference) {
+    type = resolveTypeAlias(type);
+  }
+  var dartType = type is UnionType
+      ? type.types.map((e) => e.dartType).join()
+      : type is ArrayType
+          ? 'List${_memberNameForType(type.elementType)}'
+          : type is MapType
+              ? 'Map${_memberNameForType(type.indexType)}${_memberNameForType(type.valueType)}'
+              : type.dartType;
+  return capitalize(dartType.replaceAll('?', '_'));
+}
+
 String _rewriteCommentReference(String comment) {
   final commentReferencePattern = RegExp(r'\[([\w ]+)\]\(#(\w+)\)');
   return comment.replaceAllMapped(commentReferencePattern, (m) {
@@ -319,66 +346,43 @@
   // In order to consider this valid for parsing, all fields that must not be
   // undefined must be present and also type check for the correct type.
   // Any fields that are optional but present, must still type check.
-  final fields = _getAllFields(interface);
-  for (var field in fields) {
-    if (isAnyType(field.type)) {
-      continue;
-    }
-    buffer
-      ..writeIndentedln("reporter.push('${field.name}');")
-      ..writeIndentedln('try {')
-      ..indent();
-    if (!field.allowsUndefined) {
+  final fields =
+      _getAllFields(interface).whereNot((f) => isAnyType(f.type)).toList();
+  for (var i = 0; i < fields.length; i++) {
+    final field = fields[i];
+    var type = field.type;
+    var functionName = '_canParse${_memberNameForType(type)}';
+    var invocation = "$functionName(obj, reporter, '${field.name}', "
+        'allowsUndefined: ${field.allowsUndefined}, allowsNull: ${field.allowsNull}'
+        '${type is LiteralType ? ', literal: ${type.valueAsLiteral}' : ''}'
+        '${type is LiteralUnionType ? ', literals: {${type.literalTypes.map((t) => t.valueAsLiteral).join(', ')}}' : ''}'
+        ')';
+
+    if (i == fields.length - 1) {
+      buffer.writeIndentedln('return $invocation;');
+    } else {
       buffer
-        ..writeIndentedln("if (!obj.containsKey('${field.name}')) {")
+        ..writeIndentedln("if (!$invocation) {")
         ..indent()
-        ..writeIndentedln("reporter.reportError('must not be undefined');")
-        ..writeIndentedln('return false;')
+        ..writeIndentedln("return false;")
         ..outdent()
-        ..writeIndentedln('}');
+        ..writeIndentedln("}");
     }
-    // Add a local variable to allow type promotion (and avoid multiple lookups).
-    final localName = _makeValidIdentifier(field.name);
-    buffer.writeIndentedln("final $localName = obj['${field.name}'];");
-    if (!field.allowsNull && !field.allowsUndefined) {
-      buffer
-        ..writeIndentedln('if ($localName == null) {')
-        ..indent()
-        ..writeIndentedln("reporter.reportError('must not be null');")
-        ..writeIndentedln('return false;')
-        ..outdent()
-        ..writeIndentedln('}');
+    if (!_canParseFunctions.containsKey(functionName)) {
+      var temp = IndentableStringBuffer();
+      _writeCanParseType(temp, interface, type, functionName);
+      _canParseFunctions[functionName] = temp.toString();
     }
-    buffer.writeIndented('if (');
-    final nullCheck = field.allowsNull || field.allowsUndefined;
-    if (nullCheck) {
-      buffer.write('$localName != null && ');
-    }
-    _writeTypeCheckCondition(
-        buffer, interface, localName, field.type, 'reporter',
-        negation: true, parenForCollection: nullCheck);
-    buffer
-      ..write(') {')
-      ..indent()
-      ..writeIndentedln(
-          "reporter.reportError('${_getTypeCheckFailureMessage(field.type).replaceAll("'", "\\'")}');")
-      ..writeIndentedln('return false;')
-      ..outdent()
-      ..writeIndentedln('}')
-      ..outdent()
-      ..writeIndentedln('} finally {')
-      ..indent()
-      ..writeIndentedln('reporter.pop();')
-      ..outdent()
-      ..writeIndentedln('}');
+  }
+  if (fields.isEmpty) {
+    buffer.writeIndentedln('return true;');
   }
   buffer
-    ..writeIndentedln('return true;')
     ..outdent()
     ..writeIndentedln('} else {')
     ..indent()
     ..writeIndentedln(
-        "reporter.reportError('must be of type ${interface.nameWithTypeArgs}');")
+        "reporter.reportError('must be of type ${interface.name}');")
     ..writeIndentedln('return false;')
     ..outdent()
     ..writeIndentedln('}')
@@ -386,6 +390,62 @@
     ..writeIndentedln('}');
 }
 
+void _writeCanParseType(IndentableStringBuffer buffer, Interface? interface,
+    TypeBase type, String functionName) {
+  buffer.writeln(
+      'bool $functionName(Map<String, Object?> map, LspJsonReporter reporter, '
+      'String fieldName, {required bool allowsUndefined, required bool allowsNull'
+      '${type is LiteralType ? ', required String literal' : ''}'
+      '${type is LiteralUnionType ? ', required Iterable<String> literals' : ''}'
+      '}) {');
+
+  buffer
+    ..writeIndentedln("reporter.push(fieldName);")
+    ..writeIndentedln('try {')
+    ..indent();
+  buffer
+    ..writeIndentedln("if (!allowsUndefined && !map.containsKey(fieldName)) {")
+    ..indent()
+    ..writeIndentedln("reporter.reportError('must not be undefined');")
+    ..writeIndentedln('return false;')
+    ..outdent()
+    ..writeIndentedln('}');
+
+  buffer.writeIndentedln("final value = map[fieldName];");
+  buffer.writeIndentedln("final nullCheck = allowsNull || allowsUndefined;");
+  buffer
+    ..writeIndentedln("if (!nullCheck && value == null) {")
+    ..indent()
+    ..writeIndentedln("reporter.reportError('must not be null');")
+    ..writeIndentedln('return false;')
+    ..outdent()
+    ..writeIndentedln('}');
+
+  buffer.writeIndented("if ((!nullCheck || value != null) && ");
+  _writeTypeCheckCondition(buffer, interface, 'value', type, 'reporter',
+      negation: true, parenForCollection: true);
+
+  var failureMessage = _getTypeCheckFailureMessage(type);
+  var quote = failureMessage.contains("'") ? '"' : "'";
+
+  buffer
+    ..write(') {')
+    ..indent()
+    ..writeIndentedln("reporter.reportError($quote$failureMessage$quote);")
+    ..writeIndentedln('return false;')
+    ..outdent()
+    ..writeIndentedln('}')
+    ..outdent()
+    ..writeIndentedln('} finally {')
+    ..indent()
+    ..writeIndentedln('reporter.pop();')
+    ..outdent()
+    ..writeIndentedln('}')
+    ..writeIndentedln('return true;');
+
+  buffer.writeln("}");
+}
+
 void _writeConst(IndentableStringBuffer buffer, Constant cons) {
   _writeDocCommentsAndAnnotations(buffer, cons);
   buffer.writeIndentedln('static const ${cons.name} = ${cons.valueAsLiteral};');
@@ -475,15 +535,16 @@
     ..writeln()
     ..writeIndentedln('final ${typeOfValues.dartTypeWithTypeArgs} _value;')
     ..writeln()
-    ..writeIndentedln(
-        'static bool canParse(Object? obj, LspJsonReporter reporter) {')
-    ..indent();
+    ..writeIndented(
+        'static bool canParse(Object? obj, LspJsonReporter reporter) ');
   if (allowsAnyValue) {
-    buffer.writeIndentedln('return ');
+    buffer.writeIndentedln('=> ');
     _writeTypeCheckCondition(buffer, null, 'obj', typeOfValues, 'reporter');
     buffer.writeln(';');
   } else {
     buffer
+      ..writeIndentedln('{')
+      ..indent()
       ..writeIndentedln('switch (obj) {')
       ..indent();
     for (var cons in consts) {
@@ -495,11 +556,10 @@
       ..outdent()
       ..outdent()
       ..writeIndentedln('}')
-      ..writeIndentedln('return false;');
+      ..writeIndentedln('return false;')
+      ..outdent()
+      ..writeIndentedln('}');
   }
-  buffer
-    ..outdent()
-    ..writeIndentedln('}');
   namespace.members.whereType<Constant>().forEach((cons) {
     // We don't use any deprecated enum values, so omit them entirely.
     if (cons.isDeprecated) {
@@ -636,14 +696,7 @@
     _writeFromJsonCodeForLiteralUnion(buffer, type, valueCode,
         allowsNull: allowsNull);
   } else if (type is UnionType) {
-    var functionName = type.types.map((t) {
-      if (t is TypeReference) {
-        t = resolveTypeAlias(t);
-      }
-      var dartType =
-          t is UnionType ? t.types.map((e) => e.dartType).join() : t.dartType;
-      return capitalize(dartType);
-    }).join();
+    var functionName = type.types.map((t) => _memberNameForType(t)).join();
 
     functionName = '_either$functionName';
 
@@ -732,8 +785,8 @@
     IndentableStringBuffer buffer, Interface interface) {
   final allFields = _getAllFields(interface);
   buffer
-    ..writeIndentedln('static ${interface.nameWithTypeArgs} '
-        'fromJson${interface.typeArgsString}(Map<String, Object?> json) {')
+    ..writeIndentedln('static ${interface.name} '
+        'fromJson(Map<String, Object?> json) {')
     ..indent();
   // First check whether any of our subclasses can deserialize this.
   for (final subclassName in _subtypes[interface.name] ?? const <String>[]) {
@@ -742,7 +795,7 @@
       ..writeIndentedln(
           'if (${subclass.name}.canParse(json, nullLspJsonReporter)) {')
       ..indent()
-      ..writeln('return ${subclass.nameWithTypeArgs}.fromJson(json);')
+      ..writeIndentedln('return ${subclass.name}.fromJson(json);')
       ..outdent()
       ..writeIndentedln('}');
   }
@@ -757,7 +810,7 @@
     buffer.writeln(';');
   }
   buffer
-    ..writeIndented('return ${interface.nameWithTypeArgs}(')
+    ..writeIndented('return ${interface.name}(')
     ..write(allFields.map((field) => '${field.name}: ${field.name}, ').join())
     ..writeln(');')
     ..outdent()
@@ -767,7 +820,7 @@
 void _writeHashCode(IndentableStringBuffer buffer, Interface interface) {
   buffer
     ..writeIndentedln('@override')
-    ..writeIndentedln('int get hashCode =>');
+    ..writeIndented('int get hashCode => ');
 
   final fields = _getAllFields(interface);
 
@@ -808,7 +861,7 @@
   final isPrivate = interface.name.startsWith('_');
   _writeDocCommentsAndAnnotations(buffer, interface);
 
-  buffer.writeIndented('class ${interface.nameWithTypeArgs} ');
+  buffer.writeIndented('class ${interface.name} ');
   final allBaseTypes =
       interface.baseTypes.map((t) => t.dartTypeWithTypeArgs).toList();
   allBaseTypes.add('ToJsonable');
@@ -827,7 +880,6 @@
   // Fields.
   final consts = interface.members.whereType<Constant>().toList();
   final fields = _getAllFields(interface);
-  buffer.writeln();
   _writeMembers(buffer, interface, consts);
   buffer.writeln();
   _writeMembers(buffer, interface, fields);
@@ -934,10 +986,10 @@
 
   buffer
     ..writeIndentedln('@override')
-    ..write('Map<String, Object?> toJson() ');
+    ..writeIndented('Map<String, Object?> toJson() ');
   if (fields.isEmpty) {
     buffer
-      ..writeIndentedln('=> {};')
+      ..writeln('=> {};')
       ..writeln();
     return;
   }
@@ -945,7 +997,7 @@
   final mapName = _determineVariableName(interface,
       ['result', 'map', 'json', 'toReturn', 'results', 'value', 'values']);
   buffer
-    ..writeIndentedln('{')
+    ..writeln('{')
     ..indent()
     ..writeIndentedln('var $mapName = <String, Object?>{};');
   // ResponseMessage must confirm to JSON-RPC which says only one of
@@ -1003,7 +1055,9 @@
     buffer.write('$valueCode is$operator $fullDartType');
   } else if (type is LiteralType) {
     final equals = negation ? '!=' : '==';
-    buffer.write('$valueCode $equals ${type.valueAsLiteral}');
+    buffer.write('$valueCode $equals literal');
+  } else if (type is LiteralUnionType) {
+    buffer.write('${operator}literals.contains(value)');
   } else if (_isSpecType(type)) {
     buffer.write('$operator$dartType.canParse($valueCode, $reporter)');
   } else if (type is ArrayType) {
@@ -1043,7 +1097,7 @@
       buffer.write(')');
     }
   } else if (type is UnionType) {
-    if (parenForCollection && !negation) {
+    if (parenForCollection) {
       buffer.write('(');
     }
     var or = negation ? '&&' : '||';
@@ -1056,16 +1110,9 @@
           buffer, interface, valueCode, type.types[i], reporter,
           negation: negation);
     }
-    if (parenForCollection && !negation) {
+    if (parenForCollection) {
       buffer.write(')');
     }
-  } else if (interface != null &&
-      interface.typeArgs.any((typeArg) => typeArg == fullDartType)) {
-    final comment = '/* $operator$fullDartType.canParse($valueCode) */';
-    print(
-        'WARN: Unable to write a type check for $valueCode with generic type $fullDartType. '
-        'Please review the generated code annotated with $comment');
-    buffer.write('${negation ? 'false' : 'true'} $comment');
   } else {
     throw 'Unable to type check $valueCode against $fullDartType';
   }
diff --git a/pkg/analysis_server/tool/lsp_spec/meta_model.dart b/pkg/analysis_server/tool/lsp_spec/meta_model.dart
index f6a0835..4c2d41e 100644
--- a/pkg/analysis_server/tool/lsp_spec/meta_model.dart
+++ b/pkg/analysis_server/tool/lsp_spec/meta_model.dart
@@ -79,14 +79,12 @@
 
 /// An interface/class parsed from the LSP JSON model.
 class Interface extends LspEntity {
-  final List<String> typeArgs;
   final List<TypeReference> baseTypes;
   final List<Member> members;
 
   Interface({
     required super.name,
     super.comment,
-    this.typeArgs = const [],
     this.baseTypes = const [],
     required this.members,
   }) {
@@ -96,11 +94,6 @@
 
   Interface.inline(String name, List<Member> members)
       : this(name: name, members: members);
-
-  String get nameWithTypeArgs => '$name$typeArgsString';
-
-  String get typeArgsString =>
-      typeArgs.isNotEmpty ? '<${typeArgs.join(', ')}>' : '';
 }
 
 /// A type parsed from the LSP JSON model that has a singe literal value.
diff --git a/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart b/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart
index 336e9b4..ff348a3 100644
--- a/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart
+++ b/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart
@@ -118,7 +118,6 @@
     return Interface(
       name: interface.name,
       comment: _cleanComment(interface.comment),
-      typeArgs: interface.typeArgs,
       baseTypes: interface.baseTypes
           .where((type) => _includeTypeInOutput(type.name))
           .toList(),
@@ -313,7 +312,6 @@
       return Interface(
         name: dest.name,
         comment: dest.comment ?? source.comment,
-        typeArgs: dest.typeArgs,
         baseTypes: [...dest.baseTypes, ...source.baseTypes],
         members: [...dest.members, ...source.members],
       );
@@ -365,7 +363,6 @@
           yield Interface(
             name: newName,
             comment: type.comment,
-            typeArgs: type.typeArgs,
             baseTypes: type.baseTypes,
             members: type.members,
           );
diff --git a/pkg/analyzer/lib/src/dart/analysis/byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
index 0c096b3..ea166eb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
@@ -5,6 +5,7 @@
 import 'dart:typed_data';
 
 import 'package:analyzer/src/dart/analysis/cache.dart';
+import 'package:meta/meta.dart';
 
 /// Store of bytes associated with string keys.
 ///
@@ -14,29 +15,72 @@
 ///
 /// Note that associations are not guaranteed to be persistent. The value
 /// associated with a key can change or become `null` at any point in time.
-///
-/// TODO(scheglov) Research using asynchronous API.
 abstract class ByteStore {
   /// Return the bytes associated with the given [key].
   /// Return `null` if the association does not exist.
+  ///
+  /// If this store supports reference counting, increments it.
   Uint8List? get(String key);
 
-  /// Associate the given [bytes] with the [key].
-  void put(String key, Uint8List bytes);
+  /// Associate [bytes] with [key].
+  ///
+  /// If this store supports reference counting, returns the internalized
+  /// version of [bytes], the reference count is set to `1`.
+  ///
+  /// TODO(scheglov) Disable overwriting.
+  Uint8List putGet(String key, Uint8List bytes);
+
+  /// If this store supports reference counting, decrements it for every key
+  /// in [keys], and evicts entries with the reference count equal zero.
+  void release(Iterable<String> keys);
 }
 
 /// [ByteStore] which stores data only in memory.
 class MemoryByteStore implements ByteStore {
-  final Map<String, Uint8List> _map = {};
+  @visibleForTesting
+  final Map<String, MemoryByteStoreEntry> map = {};
 
   @override
   Uint8List? get(String key) {
-    return _map[key];
+    final entry = map[key];
+    if (entry == null) {
+      return null;
+    }
+
+    entry.refCount++;
+    return entry.bytes;
   }
 
   @override
-  void put(String key, Uint8List bytes) {
-    _map[key] = bytes;
+  Uint8List putGet(String key, Uint8List bytes) {
+    map[key] = MemoryByteStoreEntry._(bytes);
+    return bytes;
+  }
+
+  @override
+  void release(Iterable<String> keys) {
+    for (final key in keys) {
+      final entry = map[key];
+      if (entry != null) {
+        entry.refCount--;
+        if (entry.refCount == 0) {
+          map.remove(key);
+        }
+      }
+    }
+  }
+}
+
+@visibleForTesting
+class MemoryByteStoreEntry {
+  final Uint8List bytes;
+  int refCount = 1;
+
+  MemoryByteStoreEntry._(this.bytes);
+
+  @override
+  String toString() {
+    return '(length: ${bytes.length}, refCount: $refCount)';
   }
 }
 
@@ -65,10 +109,14 @@
   }
 
   @override
-  void put(String key, Uint8List bytes) {
-    _store.put(key, bytes);
+  Uint8List putGet(String key, Uint8List bytes) {
+    _store.putGet(key, bytes);
     _cache.put(key, bytes);
+    return bytes;
   }
+
+  @override
+  void release(Iterable<String> keys) {}
 }
 
 /// [ByteStore] which does not store any data.
@@ -77,5 +125,8 @@
   Uint8List? get(String key) => null;
 
   @override
-  void put(String key, Uint8List bytes) {}
+  Uint8List putGet(String key, Uint8List bytes) => bytes;
+
+  @override
+  void release(Iterable<String> keys) {}
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 25983e2..611e4fe 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -1374,7 +1374,7 @@
           String unitSignature =
               _getResolvedUnitSignature(library.file, unitResult.file);
           String unitKey = _getResolvedUnitKey(unitSignature);
-          _byteStore.put(unitKey, unitBytes);
+          _byteStore.putGet(unitKey, unitBytes);
           if (unitResult.file == file) {
             bytes = unitBytes;
             resolvedUnit = unitResult.unit;
@@ -1855,7 +1855,7 @@
       String ms = threeDigits(time.millisecond);
       String key = 'exception_${time.year}$m${d}_$h$min${sec}_$ms';
 
-      _byteStore.put(key, bytes);
+      _byteStore.putGet(key, bytes);
       return key;
     } catch (_) {
       return null;
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
index 99140ad..31c1eb3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
@@ -44,15 +44,19 @@
   Uint8List? get(String key) => _fileByteStore.get(key);
 
   @override
-  void put(String key, Uint8List bytes) {
-    _fileByteStore.put(key, bytes);
+  Uint8List putGet(String key, Uint8List bytes) {
+    _fileByteStore.putGet(key, bytes);
     // Update the current size.
     _bytesWrittenSinceCleanup += bytes.length;
     if (_bytesWrittenSinceCleanup > _maxSizeBytes ~/ 8) {
       _requestCacheCleanUp();
     }
+    return bytes;
   }
 
+  @override
+  void release(Iterable<String> keys) {}
+
   /// If the cache clean up process has not been requested yet, request it.
   Future<void> _requestCacheCleanUp() async {
     if (_cleanUpSendPortShouldBePrepared) {
@@ -176,8 +180,10 @@
   }
 
   @override
-  void put(String key, Uint8List bytes) {
-    if (!_canShard(key)) return;
+  Uint8List putGet(String key, Uint8List bytes) {
+    if (!_canShard(key)) {
+      return bytes;
+    }
 
     _writeInProgress[key] = bytes;
 
@@ -200,8 +206,13 @@
         // ignore exceptions
       }
     });
+
+    return bytes;
   }
 
+  @override
+  void release(Iterable<String> keys) {}
+
   String _getShardPath(String key) {
     var shardName = key.substring(0, 2);
     return join(_cachePath, shardName);
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index e5ded7e..193ed91 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -607,7 +607,7 @@
         unit: unlinkedUnit,
       );
       var bytes = driverUnlinkedUnit.toBytes();
-      _fsState._byteStore.put(_unlinkedKey!, bytes);
+      _fsState._byteStore.putGet(_unlinkedKey!, bytes);
       return driverUnlinkedUnit;
     });
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 4f7d8eb..9442649 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -215,7 +215,7 @@
         }
 
         resolutionBytes = linkResult.resolutionBytes;
-        byteStore.put(resolutionKey, resolutionBytes);
+        byteStore.putGet(resolutionKey, resolutionBytes);
         bytesPut += resolutionBytes.length;
 
         librariesLinkedTimer.stop();
@@ -241,7 +241,7 @@
             fileSystem: _MacroFileSystem(fileSystemState),
             libraries: macroLibraries,
           );
-          byteStore.put(macroKernelKey, macroKernelBytes);
+          byteStore.putGet(macroKernelKey, macroKernelBytes);
           bytesPut += macroKernelBytes.length;
         } else {
           bytesGet += macroKernelBytes.length;
diff --git a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
index acbd3f8..91e96e3 100644
--- a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
@@ -2,86 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:typed_data';
+@Deprecated('Use ByteStore directly instead')
+library cider_byte_store;
 
-import 'package:meta/meta.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 
-/// Store of bytes associated with string keys and a hash.
-///
-/// Each key must be not longer than 100 characters and consist of only `[a-z]`,
-/// `[0-9]`, `.` and `_` characters. The key cannot be an empty string, the
-/// literal `.`, or contain the sequence `..`.
-///
-/// Note that associations are not guaranteed to be persistent. The value
-/// associated with a key can change or become `null` at any point in time.
-abstract class CiderByteStore {
-  /// Return the bytes associated with the [key], and increment the reference
-  /// count.
-  ///
-  /// Return `null` if the association does not exist.
-  Uint8List? get(String key);
-
-  /// Associate [bytes] with [key].
-  /// Return an internalized version of [bytes], the reference count is `1`.
-  ///
-  /// This method will throw an exception if there is already an association
-  /// for the [key]. The client should either use [get] to access data,
-  /// or first [release] it.
-  Uint8List putGet(String key, Uint8List bytes);
-
-  ///  Decrement the reference count for every key in [keys].
-  void release(Iterable<String> keys);
-}
-
-/// [CiderByteStore] that keeps all data in local memory.
-class MemoryCiderByteStore implements CiderByteStore {
-  @visibleForTesting
-  final Map<String, MemoryCiderByteStoreEntry> map = {};
-
-  @override
-  Uint8List? get(String key) {
-    final entry = map[key];
-    if (entry == null) {
-      return null;
-    }
-
-    entry.refCount++;
-    return entry.bytes;
-  }
-
-  @override
-  Uint8List putGet(String key, Uint8List bytes) {
-    if (map.containsKey(key)) {
-      throw StateError('Overwriting is not allowed: $key');
-    }
-
-    map[key] = MemoryCiderByteStoreEntry._(bytes);
-    return bytes;
-  }
-
-  @override
-  void release(Iterable<String> keys) {
-    for (final key in keys) {
-      final entry = map[key];
-      if (entry != null) {
-        entry.refCount--;
-        if (entry.refCount == 0) {
-          map.remove(key);
-        }
-      }
-    }
-  }
-}
-
-@visibleForTesting
-class MemoryCiderByteStoreEntry {
-  final Uint8List bytes;
-  int refCount = 1;
-
-  MemoryCiderByteStoreEntry._(this.bytes);
-
-  @override
-  String toString() {
-    return '(length: ${bytes.length}, refCount: $refCount)';
-  }
-}
+@Deprecated('Use ByteStore directly instead')
+typedef CiderByteStore = ByteStore;
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index f740eb1..12c250f 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -14,12 +14,12 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
 import 'package:analyzer/src/dart/analysis/unlinked_data.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/parser.dart';
@@ -271,7 +271,7 @@
 
 class FileSystemState {
   final ResourceProvider _resourceProvider;
-  final CiderByteStore _byteStore;
+  final ByteStore _byteStore;
   final SourceFactory _sourceFactory;
   final Workspace _workspace;
   final Uint32List _linkedSalt;
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 1224e31..92f57a8 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/context/packages.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/cache.dart';
 import 'package:analyzer/src/dart/analysis/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' show ErrorEncoding;
@@ -22,7 +23,6 @@
 import 'package:analyzer/src/dart/analysis/results.dart';
 import 'package:analyzer/src/dart/analysis/search.dart';
 import 'package:analyzer/src/dart/micro/analysis_context.dart';
-import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
 import 'package:analyzer/src/dart/micro/library_analyzer.dart';
 import 'package:analyzer/src/dart/micro/library_graph.dart';
 import 'package:analyzer/src/dart/micro/utils.dart';
@@ -87,7 +87,7 @@
 class FileResolver {
   final PerformanceLog logger;
   final ResourceProvider resourceProvider;
-  CiderByteStore byteStore;
+  ByteStore byteStore;
   final SourceFactory sourceFactory;
 
   /// A function that returns the digest for a file as a String. The function
@@ -854,7 +854,7 @@
   final FileResolverTestView? testData;
   final PerformanceLog logger;
   final ResourceProvider resourceProvider;
-  final CiderByteStore byteStore;
+  final ByteStore byteStore;
   final MicroContextObjects contextObjects;
 
   Set<LibraryCycle> loadedBundles = Set.identity();
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index b41bafc..7cefd00 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -1251,7 +1251,7 @@
         contentHashBuilder.addString(content);
         contentHashBytes = contentHashBuilder.toByteList();
 
-        tracker._byteStore.put(pathKey, contentHashBytes);
+        tracker._byteStore.putGet(pathKey, contentHashBytes);
       }
 
       contentKey = '${hex.encode(contentHashBytes)}.declarations';
@@ -1844,7 +1844,7 @@
           templateNames: templateNames, templateValues: templateValues),
     );
     var bytes = builder.toBuffer();
-    tracker._byteStore.put(contentKey, bytes);
+    tracker._byteStore.putGet(contentKey, bytes);
   }
 
   void _readFileDeclarationsFromBytes(List<int> bytes) {
diff --git a/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart b/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
index 6cf3fea..e8d0fba 100644
--- a/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
@@ -29,9 +29,9 @@
     cachingStore.get('1');
 
     // Add enough data to the store to force an eviction.
-    cachingStore.put('2', _b(40));
-    cachingStore.put('3', _b(40));
-    cachingStore.put('4', _b(40));
+    cachingStore.putGet('2', _b(40));
+    cachingStore.putGet('3', _b(40));
+    cachingStore.putGet('4', _b(40));
   }
 
   test_get_notFound_retry() {
@@ -43,7 +43,7 @@
     expect(cachingStore.get('1'), isNull);
 
     // Add data to the base store, bypassing the caching store.
-    baseStore.put('1', _b(40));
+    baseStore.putGet('1', _b(40));
 
     // Request '1' again.  The previous `null` result should not have been
     // cached.
@@ -55,8 +55,8 @@
     var cachingStore = MemoryCachingByteStore(store, 100);
 
     // Keys: [1, 2].
-    cachingStore.put('1', _b(40));
-    cachingStore.put('2', _b(50));
+    cachingStore.putGet('1', _b(40));
+    cachingStore.putGet('2', _b(50));
 
     // Request '1', so now it is the most recently used.
     // Keys: [2, 1].
@@ -64,7 +64,7 @@
 
     // 40 + 50 + 30 > 100
     // So, '2' is evicted.
-    cachingStore.put('3', _b(30));
+    cachingStore.putGet('3', _b(30));
     expect(cachingStore.get('1'), hasLength(40));
     expect(cachingStore.get('2'), isNull);
     expect(cachingStore.get('3'), hasLength(30));
@@ -75,14 +75,14 @@
     var cachingStore = MemoryCachingByteStore(store, 100);
 
     // 40 + 50 < 100
-    cachingStore.put('1', _b(40));
-    cachingStore.put('2', _b(50));
+    cachingStore.putGet('1', _b(40));
+    cachingStore.putGet('2', _b(50));
     expect(cachingStore.get('1'), hasLength(40));
     expect(cachingStore.get('2'), hasLength(50));
 
     // 40 + 50 + 30 > 100
     // So, '1' is evicted.
-    cachingStore.put('3', _b(30));
+    cachingStore.putGet('3', _b(30));
     expect(cachingStore.get('1'), isNull);
     expect(cachingStore.get('2'), hasLength(50));
     expect(cachingStore.get('3'), hasLength(30));
@@ -93,14 +93,14 @@
     var cachingStore = MemoryCachingByteStore(store, 100);
 
     // 10 + 80 < 100
-    cachingStore.put('1', _b(10));
-    cachingStore.put('2', _b(80));
+    cachingStore.putGet('1', _b(10));
+    cachingStore.putGet('2', _b(80));
     expect(cachingStore.get('1'), hasLength(10));
     expect(cachingStore.get('2'), hasLength(80));
 
     // 10 + 80 + 30 > 100
     // So, '1' and '2' are evicted.
-    cachingStore.put('3', _b(30));
+    cachingStore.putGet('3', _b(30));
     expect(cachingStore.get('1'), isNull);
     expect(cachingStore.get('2'), isNull);
     expect(cachingStore.get('3'), hasLength(30));
@@ -114,7 +114,7 @@
 
     expect(store.get('1'), isNull);
 
-    store.put('1', _b(10));
+    store.putGet('1', _b(10));
     expect(store.get('1'), isNull);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 4291c64..690c472 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -2727,7 +2727,7 @@
     expect(file.unlinked2, isNotNull);
 
     // Make the unlinked unit in the byte store zero-length, damaged.
-    byteStore.put(file.test.unlinkedKey, Uint8List(0));
+    byteStore.putGet(file.test.unlinkedKey, Uint8List(0));
 
     // Refresh should not fail, zero bytes in the store are ignored.
     file.refresh();
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index fefd22b..4aedd00 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -6,8 +6,8 @@
 
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
 import 'package:analyzer/src/dart/micro/library_graph.dart';
 import 'package:analyzer/src/dart/micro/resolve_file.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
@@ -29,7 +29,7 @@
 class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
   static final String _testFile = '/workspace/dart/test/lib/test.dart';
 
-  final MemoryCiderByteStore byteStore = MemoryCiderByteStore();
+  final MemoryByteStore byteStore = MemoryByteStore();
 
   final FileResolverTestView testData = FileResolverTestView();
 
@@ -167,7 +167,7 @@
 
   ResolverStatePrinter(this._resourceProvider, this._sink, this._keyShorter);
 
-  void write(MemoryCiderByteStore byteStore, FileSystemState fileSystemState,
+  void write(MemoryByteStore byteStore, FileSystemState fileSystemState,
       LibraryContext libraryContext, FileResolverTestView testData) {
     _writelnWithIndent('files');
     _withIndent(() {
diff --git a/pkg/compiler/lib/src/deferred_load/output_unit.dart b/pkg/compiler/lib/src/deferred_load/output_unit.dart
index 5d8345f0..cea65c21 100644
--- a/pkg/compiler/lib/src/deferred_load/output_unit.dart
+++ b/pkg/compiler/lib/src/deferred_load/output_unit.dart
@@ -10,7 +10,7 @@
 import '../constants/values.dart'
     show ConstantValue, DeferredGlobalConstantValue;
 import '../elements/entities.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../options.dart';
 
 // TODO(48820): Move OutputUnit and compareImportEntities back here.
diff --git a/pkg/compiler/lib/src/inferrer/engine.dart b/pkg/compiler/lib/src/inferrer/engine.dart
index d3aeab1..997d067 100644
--- a/pkg/compiler/lib/src/inferrer/engine.dart
+++ b/pkg/compiler/lib/src/inferrer/engine.dart
@@ -24,7 +24,7 @@
 import '../js_model/locals.dart';
 import '../native/behavior.dart';
 import '../options.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
 import '../universe/side_effects.dart';
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
index 998b848..b2fea8e 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
@@ -9,7 +9,7 @@
 import '../../elements/names.dart';
 import '../../elements/types.dart' show DartType;
 import '../../ir/class_relation.dart';
-import '../../serialization/serialization.dart';
+import '../../serialization/serialization_interfaces.dart';
 import '../../universe/selector.dart';
 import '../../universe/world_builder.dart';
 import '../../universe/use.dart';
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index cdccaa4..da421b9 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -15,7 +15,7 @@
 import '../../elements/names.dart';
 import '../../elements/types.dart';
 import '../../ir/class_relation.dart';
-import '../../serialization/serialization.dart';
+import '../../serialization/serialization_interfaces.dart';
 import '../../universe/class_hierarchy.dart';
 import '../../universe/selector.dart' show Selector;
 import '../../universe/use.dart' show DynamicUse;
diff --git a/pkg/compiler/lib/src/inferrer/wrapped.dart b/pkg/compiler/lib/src/inferrer/wrapped.dart
index 21717cb..21a7473 100644
--- a/pkg/compiler/lib/src/inferrer/wrapped.dart
+++ b/pkg/compiler/lib/src/inferrer/wrapped.dart
@@ -9,7 +9,7 @@
 import '../elements/names.dart';
 import '../elements/types.dart' show DartType;
 import '../ir/class_relation.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../universe/selector.dart';
 import '../universe/world_builder.dart';
 import '../universe/use.dart';
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index 37ef534..30138eb 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -10,7 +10,7 @@
 import '../elements/types.dart';
 import '../ir/runtime_type_analysis.dart';
 import '../kernel/kernel_strategy.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../universe/feature.dart';
 import '../util/util.dart' show Setlet;
 import 'backend_impact.dart';
diff --git a/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart b/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
index 2e24fe1..dc85fab 100644
--- a/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
+++ b/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
@@ -10,7 +10,7 @@
 import '../common/elements.dart' show JCommonElements;
 import '../elements/entities.dart';
 import '../js/js.dart' as js;
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../util/util.dart';
 import '../js_emitter/model.dart';
 import '../constants/values.dart' show ConstantValue;
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index 4076ead..b22fb53 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -14,13 +14,13 @@
 import '../elements/types.dart';
 import '../ir/scope_visitor.dart';
 import '../js_model/elements.dart' show JField;
-import '../js_model/js_world_builder.dart';
+import '../js_model/js_world_builder.dart' show JsToFrontendMap;
 import '../kernel/element_map.dart';
 import '../kernel/kernel_strategy.dart';
 import '../kernel/kelements.dart' show KClass, KField, KConstructor;
 import '../kernel/kernel_world.dart';
 import '../options.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../universe/member_usage.dart';
 
 /// AllocatorAnalysis
diff --git a/pkg/compiler/lib/src/js_backend/inferred_data.dart b/pkg/compiler/lib/src/js_backend/inferred_data.dart
index 84a067a..6e96121 100644
--- a/pkg/compiler/lib/src/js_backend/inferred_data.dart
+++ b/pkg/compiler/lib/src/js_backend/inferred_data.dart
@@ -9,7 +9,7 @@
 import '../common.dart';
 import '../elements/entities.dart';
 import '../inferrer/abstract_value_domain.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../universe/selector.dart';
 import '../universe/side_effects.dart';
 import '../world.dart';
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index 299dd02..32cadd1 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -13,7 +13,7 @@
 import '../elements/types.dart';
 import '../inferrer/abstract_value_domain.dart';
 import '../js/js.dart' as jsAst;
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../universe/class_set.dart';
 import '../universe/selector.dart';
 import '../world.dart' show JClosedWorld;
diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
index 9b9cc0d..c62f4a3 100644
--- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
+++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
@@ -10,7 +10,7 @@
 import '../elements/entities.dart';
 import '../inferrer/types.dart';
 import '../kernel/no_such_method_resolver.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 
 /// [NoSuchMethodRegistry] and [NoSuchMethodData] categorizes `noSuchMethod`
 /// implementations.
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 9791f4a..61c15b4 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -16,7 +16,7 @@
 import '../kernel/kelements.dart';
 import '../kernel/kernel_world.dart';
 import '../options.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../universe/class_hierarchy.dart';
 import '../universe/class_set.dart';
 import '../universe/feature.dart';
diff --git a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
index c893ffd..5c2e61b 100644
--- a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
+++ b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
@@ -7,6 +7,7 @@
 import '../constants/values.dart' show ConstantValue;
 import '../elements/entities.dart';
 import '../elements/types.dart' show DartType;
+import '../inferrer/abstract_value_domain.dart' show AbstractValue;
 
 export 'tags.dart';
 
@@ -61,9 +62,17 @@
 
   void writeClass(covariant ClassEntity value); // IndexedClass
   void writeClassOrNull(covariant ClassEntity? value); // IndexedClass
+  void writeClasses(Iterable<ClassEntity> values, {bool allowNull = false});
+  void writeClassMap<V>(Map<ClassEntity, V>? map, void f(V value),
+      {bool allowNull = false});
+
   void writeTypeVariable(
       covariant TypeVariableEntity value); // IndexedTypeVariable
 
+  void writeMember(covariant MemberEntity member); // IndexMember
+  void writeMemberOrNull(covariant MemberEntity? member); // IndexMember
+  void writeMembers(Iterable<MemberEntity>? values, {bool allowNull = false});
+
   void writeMemberMap<V>(
       Map<MemberEntity, V>? map, void f(MemberEntity member, V value),
       {bool allowNull = false});
@@ -89,6 +98,19 @@
       {bool allowNull = false});
 
   void writeConstant(ConstantValue value);
+  void writeConstantOrNull(ConstantValue? value);
+  void writeConstantMap<V>(Map<ConstantValue, V>? map, void f(V value),
+      {bool allowNull = false});
+
+  void writeValueOrNull<E>(E? value, void f(E value));
+
+  void writeImport(ImportEntity import);
+  void writeImportOrNull(ImportEntity? import);
+  void writeImports(Iterable<ImportEntity>? values, {bool allowNull = false});
+  void writeImportMap<V>(Map<ImportEntity, V>? map, void f(V value),
+      {bool allowNull = false});
+
+  void writeAbstractValue(AbstractValue value);
 }
 
 /// Migrated interface for methods of DataSourceReader.
@@ -112,8 +134,17 @@
 
   ClassEntity readClass(); // IndexedClass
   ClassEntity? readClassOrNull(); // IndexedClass
+  List<E> readClasses<E extends ClassEntity>();
+  List<E>? readClassesOrNull<E extends ClassEntity>();
+  Map<K, V> readClassMap<K extends ClassEntity, V>(V f());
+  Map<K, V>? readClassMapOrNull<K extends ClassEntity, V>(V f());
+
   TypeVariableEntity readTypeVariable(); // IndexedTypeVariable
 
+  MemberEntity readMember();
+  MemberEntity? readMemberOrNull();
+  List<E> readMembers<E extends MemberEntity>();
+  List<E>? readMembersOrNull<E extends MemberEntity>();
   Map<K, V> readMemberMap<K extends MemberEntity, V>(V f(MemberEntity member));
   Map<K, V>? readMemberMapOrNull<K extends MemberEntity, V>(
       V f(MemberEntity member));
@@ -140,6 +171,20 @@
   List<E>? readListOrNull<E extends Object>(E f());
 
   ConstantValue readConstant();
+  ConstantValue? readConstantOrNull();
+  Map<K, V> readConstantMap<K extends ConstantValue, V>(V f());
+  Map<K, V>? readConstantMapOrNull<K extends ConstantValue, V>(V f());
+
+  E? readValueOrNull<E>(E f());
+
+  ImportEntity readImport();
+  ImportEntity? readImportOrNull();
+  List<ImportEntity> readImports();
+  List<ImportEntity>? readImportsOrNull();
+  Map<ImportEntity, V> readImportMap<V>(V f());
+  Map<ImportEntity, V>? readImportMapOrNull<V>(V f());
+
+  AbstractValue readAbstractValue();
 
   E readWithSource<E>(DataSourceReader source, E f());
   E readWithOffset<E>(int offset, E f());
diff --git a/pkg/compiler/lib/src/serialization/sink.dart b/pkg/compiler/lib/src/serialization/sink.dart
index 4f1231e..0d3bef6 100644
--- a/pkg/compiler/lib/src/serialization/sink.dart
+++ b/pkg/compiler/lib/src/serialization/sink.dart
@@ -151,6 +151,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readValueOrNull].
+  @override
   void writeValueOrNull<E>(E value, void f(E value)) {
     writeBool(value != null);
     if (value != null) {
@@ -766,6 +767,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readClasses].
+  @override
   void writeClasses(Iterable<ClassEntity> values, {bool allowNull = false}) {
     if (values == null) {
       assert(allowNull);
@@ -784,6 +786,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readClassMap].
+  @override
   void writeClassMap<V>(Map<ClassEntity, V> map, void f(V value),
       {bool allowNull = false}) {
     if (map == null) {
@@ -799,6 +802,7 @@
   }
 
   /// Writes a reference to the indexed member [value] to this data sink.
+  @override
   void writeMember(IndexedMember value) {
     _entityWriter.writeMemberToDataSink(this, value);
   }
@@ -808,6 +812,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readMemberOrNull].
+  @override
   void writeMemberOrNull(IndexedMember value) {
     writeBool(value != null);
     if (value != null) {
@@ -820,6 +825,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readMembers].
+  @override
   void writeMembers(Iterable<MemberEntity> values, {bool allowNull = false}) {
     if (values == null) {
       assert(allowNull);
@@ -1048,6 +1054,7 @@
   }
 
   /// Writes the potentially `null` constant [value] to this data sink.
+  @override
   void writeConstantOrNull(ConstantValue value) {
     writeBool(value != null);
     if (value != null) {
@@ -1079,6 +1086,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readConstantMap].
+  @override
   void writeConstantMap<V>(Map<ConstantValue, V> map, void f(V value),
       {bool allowNull = false}) {
     if (map == null) {
@@ -1122,6 +1130,7 @@
   }
 
   /// Writes the import [value] to this data sink.
+  @override
   void writeImport(ImportEntity value) {
     _writeDataKind(DataKind.import);
     _writeImport(value);
@@ -1140,6 +1149,7 @@
   }
 
   /// Writes the potentially `null` import [value] to this data sink.
+  @override
   void writeImportOrNull(ImportEntity value) {
     writeBool(value != null);
     if (value != null) {
@@ -1152,6 +1162,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readImports].
+  @override
   void writeImports(Iterable<ImportEntity> values, {bool allowNull = false}) {
     if (values == null) {
       assert(allowNull);
@@ -1170,7 +1181,8 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readImportMap].
-  void writeImportMap<V>(Map<ImportEntity, V> map, void f(V value),
+  @override
+  void writeImportMap<V>(Map<ImportEntity, V> /*?*/ map, void f(V value),
       {bool allowNull = false}) {
     if (map == null) {
       assert(allowNull);
@@ -1187,6 +1199,7 @@
   /// Writes an abstract [value] to this data sink.
   ///
   /// This feature is only available a [CodegenWriter] has been registered.
+  @override
   void writeAbstractValue(AbstractValue value) {
     assert(_codegenWriter != null,
         "Can not serialize an AbstractValue without a registered codegen writer.");
diff --git a/pkg/compiler/lib/src/serialization/source.dart b/pkg/compiler/lib/src/serialization/source.dart
index 879c4a3..6136b59 100644
--- a/pkg/compiler/lib/src/serialization/source.dart
+++ b/pkg/compiler/lib/src/serialization/source.dart
@@ -273,6 +273,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeValueOrNull].
+  @override
   E readValueOrNull<E>(E f()) {
     bool hasValue = readBool();
     if (hasValue) {
@@ -982,13 +983,23 @@
   }
 
   /// Reads a list of references to indexed classes from this data source.
-  /// If [emptyAsNull] is `true`, `null` is returned instead of an empty list.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeClasses].
-  List<E> readClasses<E extends ClassEntity>({bool emptyAsNull = false}) {
+  @override
+  List<E> readClasses<E extends ClassEntity>() {
+    return readClassesOrNull<E>() ?? List.empty();
+  }
+
+  /// Reads a list of references to indexed classes from this data source.
+  /// `null` is returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeClasses].
+  @override
+  List<E> readClassesOrNull<E extends ClassEntity>() {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     List<E> list = List<E>.filled(count, null);
     for (int i = 0; i < count; i++) {
       ClassEntity cls = readClass();
@@ -998,15 +1009,25 @@
   }
 
   /// Reads a map from indexed classes to [V] values from this data source,
-  /// calling [f] to read each value from the data source. If [emptyAsNull] is
-  /// `true`, `null` is returned instead of an empty map.
+  /// calling [f] to read each value from the data source.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeClassMap].
-  Map<K, V> readClassMap<K extends ClassEntity, V>(V f(),
-      {bool emptyAsNull = false}) {
+  @override
+  Map<K, V> readClassMap<K extends ClassEntity, V>(V f()) {
+    return readClassMapOrNull<K, V>(f) ?? {};
+  }
+
+  /// Reads a map from indexed classes to [V] values from this data source,
+  /// calling [f] to read each value from the data source. `null` is returned if
+  /// the map is empty.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeClassMap].
+  @override
+  Map<K, V> /*?*/ readClassMapOrNull<K extends ClassEntity, V>(V f()) {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     Map<K, V> map = {};
     for (int i = 0; i < count; i++) {
       ClassEntity cls = readClass();
@@ -1017,12 +1038,14 @@
   }
 
   /// Reads a reference to an indexed member from this data source.
+  @override
   IndexedMember /*!*/ readMember() {
     return _entityReader.readMemberFromDataSource(this, entityLookup);
   }
 
   /// Reads a reference to a potentially `null` indexed member from this data
   /// source.
+  @override
   IndexedMember readMemberOrNull() {
     bool hasValue = readBool();
     if (hasValue) {
@@ -1035,6 +1058,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeMembers].
+  @override
   List<E /*!*/ > readMembers<E extends MemberEntity /*!*/ >() {
     return readMembersOrNull() ?? List.empty();
   }
@@ -1044,6 +1068,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeMembers].
+  @override
   List<E /*!*/ > readMembersOrNull<E extends MemberEntity /*!*/ >() {
     int count = readInt();
     if (count == 0) return null;
@@ -1263,6 +1288,7 @@
   }
 
   /// Reads a potentially `null` constant value from this data source.
+  @override
   ConstantValue readConstantOrNull() {
     bool hasClass = readBool();
     if (hasClass) {
@@ -1288,15 +1314,25 @@
   }
 
   /// Reads a map from constant values to [V] values from this data source,
-  /// calling [f] to read each value from the data source. If [emptyAsNull] is
-  /// `true`, `null` is returned instead of an empty map.
+  /// calling [f] to read each value from the data source.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeConstantMap].
-  Map<K, V> readConstantMap<K extends ConstantValue, V>(V f(),
-      {bool emptyAsNull = false}) {
+  @override
+  Map<K, V> readConstantMap<K extends ConstantValue, V>(V f()) {
+    return readConstantMapOrNull<K, V>(f) ?? {};
+  }
+
+  /// Reads a map from constant values to [V] values from this data source,
+  /// calling [f] to read each value from the data source. `null` is returned
+  /// instead of an empty map.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeConstantMap].
+  @override
+  Map<K, V> /*?*/ readConstantMapOrNull<K extends ConstantValue, V>(V f()) {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     Map<K, V> map = {};
     for (int i = 0; i < count; i++) {
       ConstantValue key = readConstant();
@@ -1334,6 +1370,7 @@
     return BigInt.parse(readString());
   }
 
+  @override
   ImportEntity readImport() {
     _checkDataKind(DataKind.import);
     return _readImport();
@@ -1353,6 +1390,7 @@
   }
 
   /// Reads a potentially `null` import from this data source.
+  @override
   ImportEntity readImportOrNull() {
     bool hasClass = readBool();
     if (hasClass) {
@@ -1361,14 +1399,24 @@
     return null;
   }
 
-  /// Reads a list of imports from this data source. If [emptyAsNull] is
-  /// `true`, `null` is returned instead of an empty list.
+  /// Reads a list of imports from this data source.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeImports].
-  List<ImportEntity> readImports({bool emptyAsNull = false}) {
+  @override
+  List<ImportEntity> readImports() {
+    return readImportsOrNull() ?? const [];
+  }
+
+  /// Reads a list of imports from this data source.
+  /// `null` is returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeImports].
+  @override
+  List<ImportEntity> /*?*/ readImportsOrNull() {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     List<ImportEntity> list = List<ImportEntity>.filled(count, null);
     for (int i = 0; i < count; i++) {
       list[i] = readImport();
@@ -1377,14 +1425,25 @@
   }
 
   /// Reads a map from imports to [V] values from this data source,
-  /// calling [f] to read each value from the data source. If [emptyAsNull] is
-  /// `true`, `null` is returned instead of an empty map.
+  /// calling [f] to read each value from the data source.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeImportMap].
-  Map<ImportEntity, V> readImportMap<V>(V f(), {bool emptyAsNull = false}) {
+  @override
+  Map<ImportEntity, V> readImportMap<V>(V f()) {
+    return readImportMapOrNull<V>(f) ?? {};
+  }
+
+  /// Reads a map from imports to [V] values from this data source, calling [f]
+  /// to read each value from the data source. `null` is returned if the map is
+  /// empty map.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeImportMap].
+  @override
+  Map<ImportEntity, V> /*?*/ readImportMapOrNull<V>(V f()) {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     Map<ImportEntity, V> map = {};
     for (int i = 0; i < count; i++) {
       ImportEntity key = readImport();
@@ -1397,6 +1456,7 @@
   /// Reads an [AbstractValue] from this data source.
   ///
   /// This feature is only available a [CodegenReader] has been registered.
+  @override
   AbstractValue readAbstractValue() {
     assert(
         _codegenReader != null,
diff --git a/pkg/compiler/lib/src/universe/member_usage.dart b/pkg/compiler/lib/src/universe/member_usage.dart
index 21027d0..9bb2a33 100644
--- a/pkg/compiler/lib/src/universe/member_usage.dart
+++ b/pkg/compiler/lib/src/universe/member_usage.dart
@@ -9,7 +9,7 @@
 import '../common.dart';
 import '../constants/values.dart';
 import '../elements/entities.dart';
-import '../js_model/closure.dart';
+import '../js_model/closure.dart' show JRecordField;
 import '../serialization/serialization_interfaces.dart';
 import '../util/enumset.dart';
 import 'call_structure.dart';
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 2adead4..28fdeed 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -23,8 +23,8 @@
 import '../elements/types.dart';
 import '../elements/entities.dart';
 import '../inferrer/abstract_value_domain.dart';
-import '../serialization/serialization.dart';
-import '../js_model/closure.dart';
+import '../serialization/serialization_interfaces.dart';
+import '../js_model/closure.dart' show JRecordField;
 import '../util/util.dart' show equalElements, Hashing;
 import 'call_structure.dart' show CallStructure;
 import 'selector.dart' show Selector;
diff --git a/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
index 8c4850d..b567677 100644
--- a/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
@@ -239,7 +239,6 @@
   inferFunctionBody,
   inferInitializer,
   inferMetadata,
-  inferMetadataKeepingHelper,
   inferParameterInitializer,
   inferRedirectingFactoryTypeArguments,
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 42acff0..419e825 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -153,7 +153,6 @@
 
   final ClassHierarchy hierarchy;
 
-  @override
   final CoreTypes coreTypes;
 
   final bool isDeclarationInstanceMember;
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index ba728a0..73e8b41 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -17,26 +17,17 @@
 /// This means that in some cases multiple shadow classes may extend the same
 /// kernel class, because multiple constructs in Dart may desugar to a tree
 /// with the same kind of root node.
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/src/printer.dart';
 import 'package:kernel/text/ast_to_text.dart' show Precedence, Printer;
 import 'package:kernel/type_environment.dart';
 
 import '../builder/type_alias_builder.dart';
-
-import '../fasta_codes.dart'
-    show noLength, templateWebLiteralCannotBeRepresentedExactly;
-
 import '../names.dart';
-
 import '../problems.dart' show unsupported;
-
-import '../type_inference/type_inferrer.dart';
-
-import '../type_inference/type_schema.dart' show UnknownType;
-
 import '../type_inference/inference_visitor.dart';
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart' show UnknownType;
 
 int getExtensionTypeParameterCount(Arguments arguments) {
   if (arguments is ArgumentsImpl) {
@@ -181,7 +172,7 @@
   R accept1<R, A>(StatementVisitor1<R, A> visitor, A arg) =>
       unsupported("${runtimeType}.accept1", -1, null);
 
-  StatementInferenceResult acceptInference(InferenceVisitor visitor);
+  StatementInferenceResult acceptInference(InferenceVisitorImpl visitor);
 }
 
 class ForInStatementWithSynthesizedVariable extends InternalStatement {
@@ -209,7 +200,7 @@
   }
 
   @override
-  StatementInferenceResult acceptInference(InferenceVisitor visitor) {
+  StatementInferenceResult acceptInference(InferenceVisitorImpl visitor) {
     return visitor.visitForInStatementWithSynthesizedVariable(this);
   }
 
@@ -301,7 +292,7 @@
   }
 
   @override
-  StatementInferenceResult acceptInference(InferenceVisitor visitor) {
+  StatementInferenceResult acceptInference(InferenceVisitorImpl visitor) {
     return visitor.visitTryStatement(this);
   }
 
@@ -472,7 +463,7 @@
       unsupported("${runtimeType}.getStaticType", -1, null);
 
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext);
+      InferenceVisitorImpl visitor, DartType typeContext);
 
   @override
   void toTextInternal(AstPrinter printer) {
@@ -631,7 +622,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitCascade(this, typeContext);
   }
 
@@ -713,7 +704,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitDeferredCheck(this, typeContext);
   }
 
@@ -774,7 +765,7 @@
   /// Calls back to [inferrer] to perform type inference for whatever concrete
   /// type of [Expression] this is.
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext);
+      InferenceVisitorImpl visitor, DartType typeContext);
 }
 
 /// Shadow object for [StaticInvocation] when the procedure being invoked is a
@@ -789,7 +780,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitFactoryConstructorInvocation(this, typeContext);
   }
 
@@ -829,7 +820,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitTypeAliasedConstructorInvocation(this, typeContext);
   }
 
@@ -869,7 +860,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitTypeAliasedFactoryInvocation(this, typeContext);
   }
 
@@ -924,7 +915,7 @@
       : super(variable);
 
   @override
-  InitializerInferenceResult acceptInference(InferenceVisitor visitor) {
+  InitializerInferenceResult acceptInference(InferenceVisitorImpl visitor) {
     return visitor.visitInvalidSuperInitializerJudgment(this);
   }
 
@@ -955,7 +946,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIfNullExpression(this, typeContext);
   }
 
@@ -1015,27 +1006,7 @@
 abstract class InitializerJudgment implements Initializer {
   /// Performs type inference for whatever concrete type of
   /// [InitializerJudgment] this is.
-  InitializerInferenceResult acceptInference(InferenceVisitor visitor);
-}
-
-Expression? checkWebIntLiteralsErrorIfUnexact(
-    InferenceVisitorBase inferrer, int value, String? literal, int charOffset) {
-  if (value >= 0 && value <= (1 << 53)) return null;
-  if (inferrer.isTopLevel) return null;
-  if (!inferrer.libraryBuilder.loader.target.backendTarget
-      .errorOnUnexactWebIntLiterals) return null;
-  BigInt asInt = new BigInt.from(value).toUnsigned(64);
-  BigInt asDouble = new BigInt.from(asInt.toDouble());
-  if (asInt == asDouble) return null;
-  String text = literal ?? value.toString();
-  String nearest = text.startsWith('0x') || text.startsWith('0X')
-      ? '0x${asDouble.toRadixString(16)}'
-      : asDouble.toString();
-  int length = literal?.length ?? noLength;
-  return inferrer.helper.buildProblem(
-      templateWebLiteralCannotBeRepresentedExactly.withArguments(text, nearest),
-      charOffset,
-      length);
+  InitializerInferenceResult acceptInference(InferenceVisitorImpl visitor);
 }
 
 /// Concrete shadow object representing an integer literal in kernel form.
@@ -1055,7 +1026,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIntJudgment(this, typeContext);
   }
 
@@ -1101,7 +1072,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitShadowLargeIntLiteral(this, typeContext);
   }
 
@@ -1122,7 +1093,7 @@
   ShadowInvalidInitializer(VariableDeclaration variable) : super(variable);
 
   @override
-  InitializerInferenceResult acceptInference(InferenceVisitor visitor) {
+  InitializerInferenceResult acceptInference(InferenceVisitorImpl visitor) {
     return visitor.visitShadowInvalidInitializer(this);
   }
 
@@ -1147,7 +1118,7 @@
   }
 
   @override
-  InitializerInferenceResult acceptInference(InferenceVisitor visitor) {
+  InitializerInferenceResult acceptInference(InferenceVisitorImpl visitor) {
     return visitor.visitShadowInvalidFieldInitializer(this);
   }
 
@@ -1172,7 +1143,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitExpressionInvocation(this, typeContext);
   }
 
@@ -1250,7 +1221,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitNullAwareMethodInvocation(this, typeContext);
   }
 
@@ -1353,7 +1324,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitNullAwarePropertyGet(this, typeContext);
   }
 
@@ -1444,7 +1415,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitNullAwarePropertySet(this, typeContext);
   }
 
@@ -1727,7 +1698,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitLoadLibraryTearOff(this, typeContext);
   }
 
@@ -1807,7 +1778,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIfNullPropertySet(this, typeContext);
   }
 
@@ -1897,7 +1868,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIfNullSet(this, typeContext);
   }
 
@@ -2043,7 +2014,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitCompoundExtensionSet(this, typeContext);
   }
 
@@ -2151,7 +2122,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitCompoundPropertySet(this, typeContext);
   }
 
@@ -2246,7 +2217,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitPropertyPostIncDec(this, typeContext);
   }
 
@@ -2321,7 +2292,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitLocalPostIncDec(this, typeContext);
   }
 
@@ -2394,7 +2365,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitStaticPostIncDec(this, typeContext);
   }
 
@@ -2467,7 +2438,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitSuperPostIncDec(this, typeContext);
   }
 
@@ -2533,7 +2504,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIndexGet(this, typeContext);
   }
 
@@ -2629,7 +2600,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIndexSet(this, typeContext);
   }
 
@@ -2730,7 +2701,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitSuperIndexSet(this, typeContext);
   }
 
@@ -2832,7 +2803,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitExtensionIndexSet(this, typeContext);
   }
 
@@ -2975,7 +2946,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIfNullIndexSet(this, typeContext);
   }
 
@@ -3100,7 +3071,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIfNullSuperIndexSet(this, typeContext);
   }
 
@@ -3227,7 +3198,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitIfNullExtensionIndexSet(this, typeContext);
   }
 
@@ -3358,7 +3329,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitCompoundIndexSet(this, typeContext);
   }
 
@@ -3528,7 +3499,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitNullAwareCompoundSet(this, typeContext);
   }
 
@@ -3665,7 +3636,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitNullAwareIfNullSet(this, typeContext);
   }
 
@@ -3793,7 +3764,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitCompoundSuperIndexSet(this, typeContext);
   }
 
@@ -3937,7 +3908,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitCompoundExtensionIndexSet(this, typeContext);
   }
 
@@ -4052,7 +4023,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitExtensionSet(this, typeContext);
   }
 
@@ -4123,7 +4094,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitNullAwareExtension(this, typeContext);
   }
 
@@ -4197,7 +4168,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitExtensionTearOff(this, typeContext);
   }
 
@@ -4252,7 +4223,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitEquals(this, typeContext);
   }
 
@@ -4327,7 +4298,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitBinary(this, typeContext);
   }
 
@@ -4397,7 +4368,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitUnary(this, typeContext);
   }
 
@@ -4458,7 +4429,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitParenthesized(this, typeContext);
   }
 
@@ -4599,7 +4570,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitMethodInvocation(this, typeContext);
   }
 
@@ -4675,7 +4646,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitPropertyGet(this, typeContext);
   }
 
@@ -4754,7 +4725,7 @@
 
   @override
   ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
+      InferenceVisitorImpl visitor, DartType typeContext) {
     return visitor.visitPropertySet(this, typeContext);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
index 8d0c67b..dc2e8fe 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
@@ -48,12 +48,12 @@
         DartType yieldContext = inferrer.getTypeArgumentOf(
             returnContext, inferrer.coreTypes.streamClass);
         return new _AsyncStarClosureContext(
-            yieldContext, declaredReturnType, needToInferReturnType);
+            inferrer, yieldContext, declaredReturnType, needToInferReturnType);
       } else {
         DartType yieldContext = inferrer.getTypeArgumentOf(
             returnContext, inferrer.coreTypes.iterableClass);
         return new _SyncStarClosureContext(
-            yieldContext, declaredReturnType, needToInferReturnType);
+            inferrer, yieldContext, declaredReturnType, needToInferReturnType);
       }
     } else if (isAsync) {
       DartType? futureValueType;
@@ -72,11 +72,11 @@
           futureValueType = flattenedType;
         }
       }
-      return new _AsyncClosureContext(returnContext, declaredReturnType,
-          needToInferReturnType, futureValueType);
+      return new _AsyncClosureContext(inferrer, returnContext,
+          declaredReturnType, needToInferReturnType, futureValueType);
     } else {
       return new _SyncClosureContext(
-          returnContext, declaredReturnType, needToInferReturnType);
+          inferrer, returnContext, declaredReturnType, needToInferReturnType);
     }
   }
 
@@ -85,16 +85,15 @@
   /// If the return type is declared, the expression type is checked. If the
   /// return type is inferred the expression type registered for inference
   /// in [inferReturnType].
-  void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
-      DartType type, bool isArrow);
+  void handleReturn(ReturnStatement statement, DartType type, bool isArrow);
 
   /// Handles an explicit yield statement.
   ///
   /// If the return type is declared, the expression type is checked. If the
   /// return type is inferred the expression type registered for inference
   /// in [inferReturnType].
-  void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
-      ExpressionInferenceResult expressionResult);
+  void handleYield(
+      YieldStatement node, ExpressionInferenceResult expressionResult);
 
   /// Handles an implicit return statement.
   ///
@@ -117,6 +116,8 @@
 }
 
 class _SyncClosureContext implements ClosureContext {
+  final InferenceVisitorBase inferrer;
+
   @override
   bool get isAsync => false;
 
@@ -152,16 +153,16 @@
   @override
   DartType? get futureValueType => null;
 
-  _SyncClosureContext(this._returnContext, this._declaredReturnType,
-      this._needToInferReturnType) {
+  _SyncClosureContext(this.inferrer, this._returnContext,
+      this._declaredReturnType, this._needToInferReturnType) {
     if (_needToInferReturnType) {
       _returnStatements = [];
       _returnExpressionTypes = [];
     }
   }
 
-  void _checkValidReturn(InferenceVisitorBase inferrer, DartType returnType,
-      ReturnStatement statement, DartType expressionType) {
+  void _checkValidReturn(
+      DartType returnType, ReturnStatement statement, DartType expressionType) {
     assert(!inferrer.isTopLevel);
     if (inferrer.isNonNullableByDefault) {
       if (statement.expression == null) {
@@ -289,8 +290,7 @@
   /// Updates the inferred return type based on the presence of a return
   /// statement returning the given [type].
   @override
-  void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
-      DartType type, bool isArrow) {
+  void handleReturn(ReturnStatement statement, DartType type, bool isArrow) {
     // The first return we see tells us if we have an arrow function.
     if (this._isArrow == null) {
       this._isArrow = isArrow;
@@ -304,13 +304,13 @@
       _returnStatements!.add(statement);
       _returnExpressionTypes!.add(type);
     } else if (!inferrer.isTopLevel) {
-      _checkValidReturn(inferrer, _declaredReturnType, statement, type);
+      _checkValidReturn(_declaredReturnType, statement, type);
     }
   }
 
   @override
-  void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
-      ExpressionInferenceResult expressionResult) {
+  void handleYield(
+      YieldStatement node, ExpressionInferenceResult expressionResult) {
     node.expression = expressionResult.expression..parent = node;
   }
 
@@ -412,7 +412,7 @@
 
     for (int i = 0; i < _returnStatements!.length; ++i) {
       if (!inferrer.isTopLevel) {
-        _checkValidReturn(inferrer, inferredReturnType, _returnStatements![i],
+        _checkValidReturn(inferredReturnType, _returnStatements![i],
             _returnExpressionTypes![i]);
       }
     }
@@ -467,6 +467,8 @@
 /// Keeps track of information about the innermost function or closure being
 /// inferred.
 class _AsyncClosureContext implements ClosureContext {
+  final InferenceVisitorBase inferrer;
+
   @override
   bool get isAsync => true;
 
@@ -505,16 +507,20 @@
   @override
   DartType? futureValueType;
 
-  _AsyncClosureContext(this._returnContext, this._declaredReturnType,
-      this._needToInferReturnType, this.futureValueType) {
+  _AsyncClosureContext(
+      this.inferrer,
+      this._returnContext,
+      this._declaredReturnType,
+      this._needToInferReturnType,
+      this.futureValueType) {
     if (_needToInferReturnType) {
       _returnStatements = [];
       _returnExpressionTypes = [];
     }
   }
 
-  void _checkValidReturn(InferenceVisitorBase inferrer, DartType returnType,
-      ReturnStatement statement, DartType expressionType) {
+  void _checkValidReturn(
+      DartType returnType, ReturnStatement statement, DartType expressionType) {
     assert(!inferrer.isTopLevel);
     if (inferrer.isNonNullableByDefault) {
       assert(
@@ -674,8 +680,7 @@
   /// Updates the inferred return type based on the presence of a return
   /// statement returning the given [type].
   @override
-  void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
-      DartType type, bool isArrow) {
+  void handleReturn(ReturnStatement statement, DartType type, bool isArrow) {
     // The first return we see tells us if we have an arrow function.
     if (this._isArrow == null) {
       this._isArrow = isArrow;
@@ -689,13 +694,13 @@
       _returnStatements!.add(statement);
       _returnExpressionTypes!.add(type);
     } else if (!inferrer.isTopLevel) {
-      _checkValidReturn(inferrer, _declaredReturnType, statement, type);
+      _checkValidReturn(_declaredReturnType, statement, type);
     }
   }
 
   @override
-  void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
-      ExpressionInferenceResult expressionResult) {
+  void handleYield(
+      YieldStatement node, ExpressionInferenceResult expressionResult) {
     node.expression = expressionResult.expression..parent = node;
   }
 
@@ -824,8 +829,8 @@
     }
     if (!inferrer.isTopLevel) {
       for (int i = 0; i < _returnStatements!.length; ++i) {
-        _checkValidReturn(inferrer, inferredType, _returnStatements![i],
-            _returnExpressionTypes![i]);
+        _checkValidReturn(
+            inferredType, _returnStatements![i], _returnExpressionTypes![i]);
       }
     }
 
@@ -880,6 +885,8 @@
 /// Keeps track of information about the innermost function or closure being
 /// inferred.
 class _SyncStarClosureContext implements ClosureContext {
+  final InferenceVisitorBase inferrer;
+
   @override
   bool get isAsync => false;
 
@@ -912,8 +919,8 @@
   @override
   DartType? get futureValueType => null;
 
-  _SyncStarClosureContext(this._yieldElementContext, this._declaredReturnType,
-      this._needToInferReturnType) {
+  _SyncStarClosureContext(this.inferrer, this._yieldElementContext,
+      this._declaredReturnType, this._needToInferReturnType) {
     if (_needToInferReturnType) {
       _yieldElementTypes = [];
     }
@@ -922,12 +929,11 @@
   /// Updates the inferred return type based on the presence of a return
   /// statement returning the given [type].
   @override
-  void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
-      DartType type, bool isArrow) {}
+  void handleReturn(ReturnStatement statement, DartType type, bool isArrow) {}
 
   @override
-  void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
-      ExpressionInferenceResult expressionResult) {
+  void handleYield(
+      YieldStatement node, ExpressionInferenceResult expressionResult) {
     DartType expectedType = node.isYieldStar
         ? inferrer.wrapType(
             _yieldElementContext,
@@ -1014,6 +1020,8 @@
 /// Keeps track of information about the innermost function or closure being
 /// inferred.
 class _AsyncStarClosureContext implements ClosureContext {
+  final InferenceVisitorBase inferrer;
+
   @override
   bool get isAsync => true;
 
@@ -1046,8 +1054,8 @@
   @override
   DartType? get futureValueType => null;
 
-  _AsyncStarClosureContext(this._yieldElementContext, this._declaredReturnType,
-      this._needToInferReturnType) {
+  _AsyncStarClosureContext(this.inferrer, this._yieldElementContext,
+      this._declaredReturnType, this._needToInferReturnType) {
     if (_needToInferReturnType) {
       _yieldElementTypes = [];
     }
@@ -1056,12 +1064,11 @@
   /// Updates the inferred return type based on the presence of a return
   /// statement returning the given [type].
   @override
-  void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
-      DartType type, bool isArrow) {}
+  void handleReturn(ReturnStatement statement, DartType type, bool isArrow) {}
 
   @override
-  void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
-      ExpressionInferenceResult expressionResult) {
+  void handleYield(
+      YieldStatement node, ExpressionInferenceResult expressionResult) {
     DartType expectedType = node.isYieldStar
         ? inferrer.wrapType(_yieldElementContext,
             inferrer.coreTypes.streamClass, inferrer.libraryBuilder.nonNullable)
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
index e8e2c91..e8333c9 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
@@ -4,13 +4,9 @@
 
 import 'package:kernel/ast.dart';
 
-import 'package:kernel/core_types.dart' show CoreTypes;
-
 import '../fasta_codes.dart' show LocatedMessage, Message;
 
 abstract class InferenceHelper {
-  CoreTypes get coreTypes;
-
   Uri get uri;
 
   set transformSetLiterals(bool value);
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
index 836e680..49d9760 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
@@ -34,39 +34,63 @@
 import '../names.dart';
 import '../problems.dart' show unhandled;
 import '../source/source_library_builder.dart';
+import 'inference_helper.dart';
 import 'type_constraint_gatherer.dart';
 import 'type_inference_engine.dart';
 import 'type_inferrer.dart';
 import 'type_schema.dart' show UnknownType;
 
-class InferenceVisitor
-    implements
-        ExpressionVisitor1<ExpressionInferenceResult, DartType>,
-        StatementVisitor<StatementInferenceResult>,
-        InitializerVisitor<InitializerInferenceResult> {
-  final InferenceVisitorBase inferrer;
-
-  Class? mapEntryClass;
-
-  /// Context information for the current closure, or `null` if we are not
-  /// inside a closure.
-  ClosureContext? _closureContext;
-
-  InferenceVisitor(this.inferrer);
-
-  ClosureContext get closureContext => _closureContext!;
+abstract class InferenceVisitor {
+  /// Performs type inference on the given [expression].
+  ///
+  /// [typeContext] is the expected type of the expression, based on surrounding
+  /// code.  [typeNeeded] indicates whether it is necessary to compute the
+  /// actual type of the expression.  If [typeNeeded] is `true`,
+  /// [ExpressionInferenceResult.inferredType] is the actual type of the
+  /// expression; otherwise the [UnknownType].
+  ///
+  /// Derived classes should override this method with logic that dispatches on
+  /// the expression type and calls the appropriate specialized "infer" method.
+  ExpressionInferenceResult inferExpression(
+      Expression expression, DartType typeContext, bool typeNeeded,
+      {bool isVoidAllowed: false, bool forEffect: false});
 
   /// Performs type inference on the given [statement].
   ///
   /// If [closureContext] is not null, the [statement] is inferred using
   /// [closureContext] as the current context.
   StatementInferenceResult inferStatement(Statement statement,
+      [ClosureContext? closureContext]);
+
+  /// Performs type inference on the given [initializer].
+  InitializerInferenceResult inferInitializer(Initializer initializer);
+}
+
+class InferenceVisitorImpl extends InferenceVisitorBase
+    implements
+        ExpressionVisitor1<ExpressionInferenceResult, DartType>,
+        StatementVisitor<StatementInferenceResult>,
+        InitializerVisitor<InitializerInferenceResult>,
+        InferenceVisitor {
+  Class? mapEntryClass;
+
+  /// Context information for the current closure, or `null` if we are not
+  /// inside a closure.
+  ClosureContext? _closureContext;
+
+  InferenceVisitorImpl(TypeInferrerImpl inferrer, InferenceHelper? helper)
+      : super(inferrer, helper);
+
+  ClosureContext get closureContext => _closureContext!;
+
+  @override
+  StatementInferenceResult inferStatement(Statement statement,
       [ClosureContext? closureContext]) {
     ClosureContext? oldClosureContext = _closureContext;
     if (closureContext != null) {
       _closureContext = closureContext;
     }
-    inferrer.registerIfUnreachableForTesting(statement);
+    registerIfUnreachableForTesting(statement);
 
     // For full (non-top level) inference, we need access to the
     // ExpressionGeneratorHelper so that we can perform error recovery.
@@ -80,20 +104,10 @@
     return result;
   }
 
-  /// Performs type inference on the given [expression].
-  ///
-  /// [typeContext] is the expected type of the expression, based on surrounding
-  /// code.  [typeNeeded] indicates whether it is necessary to compute the
-  /// actual type of the expression.  If [typeNeeded] is `true`,
-  /// [ExpressionInferenceResult.inferredType] is the actual type of the
-  /// expression; otherwise `null`.
-  ///
-  /// Derived classes should override this method with logic that dispatches on
-  /// the expression type and calls the appropriate specialized "infer" method.
   ExpressionInferenceResult _inferExpression(
       Expression expression, DartType typeContext, bool typeNeeded,
       {bool isVoidAllowed: false, bool forEffect: false}) {
-    inferrer.registerIfUnreachableForTesting(expression);
+    registerIfUnreachableForTesting(expression);
 
     // `null` should never be used as the type context.  An instance of
     // `UnknownType` should be used instead.
@@ -120,23 +134,23 @@
     assert(inferredType != null,
         "No type inferred for $expression (${expression.runtimeType}).");
     if (inferredType is VoidType && !isVoidAllowed) {
-      if (expression.parent is! ArgumentsImpl && !inferrer.isTopLevel) {
-        inferrer.helper
-            .addProblem(messageVoidExpression, expression.fileOffset, noLength);
+      if (expression.parent is! ArgumentsImpl && !isTopLevel) {
+        helper.addProblem(
+            messageVoidExpression, expression.fileOffset, noLength);
       }
     }
-    if (inferrer.coreTypes.isBottom(result.inferredType)) {
-      inferrer.flowAnalysis.handleExit();
-      if (inferrer.shouldThrowUnsoundnessException &&
+    if (coreTypes.isBottom(result.inferredType)) {
+      flowAnalysis.handleExit();
+      if (shouldThrowUnsoundnessException &&
           // Don't throw on expressions that inherently return the bottom type.
           !(result.nullAwareAction is Throw ||
               result.nullAwareAction is Rethrow ||
               result.nullAwareAction is InvalidExpression)) {
         Expression replacement = createLet(
             createVariable(result.expression, result.inferredType),
-            inferrer.createReachabilityError(expression.fileOffset,
+            createReachabilityError(expression.fileOffset,
                 messageNeverValueError, messageNeverValueWarning));
-        inferrer.flowAnalysis.forwardExpression(replacement, result.expression);
+        flowAnalysis.forwardExpression(replacement, result.expression);
         result =
             new ExpressionInferenceResult(result.inferredType, replacement);
       }
@@ -144,6 +158,7 @@
     return result;
   }
 
+  @override
   ExpressionInferenceResult inferExpression(
       Expression expression, DartType typeContext, bool typeNeeded,
       {bool isVoidAllowed: false, bool forEffect: false}) {
@@ -153,13 +168,24 @@
     return result.stopShorting();
   }
 
+  @override
+  InitializerInferenceResult inferInitializer(Initializer initializer) {
+    InitializerInferenceResult inferenceResult;
+    if (initializer is InitializerJudgment) {
+      inferenceResult = initializer.acceptInference(this);
+    } else {
+      inferenceResult = initializer.accept(this);
+    }
+    return inferenceResult;
+  }
+
   ExpressionInferenceResult inferNullAwareExpression(
       Expression expression, DartType typeContext, bool typeNeeded,
       {bool isVoidAllowed: false, bool forEffect: false}) {
     ExpressionInferenceResult result = _inferExpression(
         expression, typeContext, typeNeeded,
         isVoidAllowed: isVoidAllowed, forEffect: forEffect);
-    if (inferrer.isNonNullableByDefault) {
+    if (isNonNullableByDefault) {
       return result;
     } else {
       return result.stopShorting();
@@ -173,12 +199,9 @@
         variable.initializer!, const UnknownType(), true,
         isVoidAllowed: true);
     variable.initializer = result.expression..parent = variable;
-    DartType inferredType = inferrer.inferDeclarationType(result.inferredType,
-        forSyntheticVariable: true);
-    inferrer.instrumentation?.record(
-        inferrer.uriForInstrumentation,
-        variable.fileOffset,
-        'type',
+    DartType inferredType =
+        inferDeclarationType(result.inferredType, forSyntheticVariable: true);
+    instrumentation?.record(uriForInstrumentation, variable.fileOffset, 'type',
         new InstrumentationValueForType(inferredType));
     variable.type = inferredType;
   }
@@ -194,12 +217,9 @@
     Link<NullAwareGuard> nullAwareGuards = result.nullAwareGuards;
     variable.initializer = result.nullAwareAction..parent = variable;
 
-    DartType inferredType = inferrer.inferDeclarationType(result.inferredType,
-        forSyntheticVariable: true);
-    inferrer.instrumentation?.record(
-        inferrer.uriForInstrumentation,
-        variable.fileOffset,
-        'type',
+    DartType inferredType =
+        inferDeclarationType(result.inferredType, forSyntheticVariable: true);
+    instrumentation?.record(uriForInstrumentation, variable.fileOffset, 'type',
         new InstrumentationValueForType(inferredType));
     variable.type = inferredType;
     return nullAwareGuards;
@@ -210,9 +230,9 @@
   _UriOffset _computeUriOffset(TreeNode node) {
     Uri uri;
     int fileOffset;
-    if (!inferrer.isTopLevel) {
+    if (!isTopLevel) {
       // In local inference we have access to the current file uri.
-      uri = inferrer.helper.uri;
+      uri = helper.uri;
       fileOffset = node.fileOffset;
     } else {
       Location? location = node.location;
@@ -222,7 +242,7 @@
         fileOffset = node.fileOffset;
       } else {
         // Otherwise use the library file uri with no offset.
-        uri = inferrer.libraryBuilder.fileUri;
+        uri = libraryBuilder.fileUri;
         fileOffset = TreeNode.noOffset;
       }
     }
@@ -253,7 +273,7 @@
       BlockExpression node, DartType typeContext) {
     // This is only used for error cases. The spec doesn't use this and
     // therefore doesn't specify the type context for the subterms.
-    if (!inferrer.isTopLevel) {
+    if (!isTopLevel) {
       StatementInferenceResult bodyResult = inferStatement(node.body);
       if (bodyResult.hasChanged) {
         node.body = (bodyResult.statement as Block)..parent = node;
@@ -283,8 +303,7 @@
         resultType = const DynamicType();
         break;
       case DynamicAccessKind.Never:
-        resultType =
-            NeverType.fromNullability(inferrer.libraryBuilder.nonNullable);
+        resultType = NeverType.fromNullability(libraryBuilder.nonNullable);
         break;
       case DynamicAccessKind.Invalid:
       case DynamicAccessKind.Unresolved:
@@ -363,10 +382,10 @@
   @override
   ExpressionInferenceResult visitStaticTearOff(
       StaticTearOff node, DartType typeContext) {
-    inferrer.ensureMemberType(node.target);
-    DartType type = node.target.function
-        .computeFunctionType(inferrer.libraryBuilder.nonNullable);
-    return inferrer.instantiateTearOff(type, typeContext, node);
+    ensureMemberType(node.target);
+    DartType type =
+        node.target.function.computeFunctionType(libraryBuilder.nonNullable);
+    return instantiateTearOff(type, typeContext, node);
   }
 
   @override
@@ -390,18 +409,18 @@
   @override
   ExpressionInferenceResult visitConstructorTearOff(
       ConstructorTearOff node, DartType typeContext) {
-    inferrer.ensureMemberType(node.target);
-    DartType type = node.target.function!
-        .computeFunctionType(inferrer.libraryBuilder.nonNullable);
-    return inferrer.instantiateTearOff(type, typeContext, node);
+    ensureMemberType(node.target);
+    DartType type =
+        node.target.function!.computeFunctionType(libraryBuilder.nonNullable);
+    return instantiateTearOff(type, typeContext, node);
   }
 
   @override
   ExpressionInferenceResult visitRedirectingFactoryTearOff(
       RedirectingFactoryTearOff node, DartType typeContext) {
-    DartType type = node.target.function
-        .computeFunctionType(inferrer.libraryBuilder.nonNullable);
-    return inferrer.instantiateTearOff(type, typeContext, node);
+    DartType type =
+        node.target.function.computeFunctionType(libraryBuilder.nonNullable);
+    return instantiateTearOff(type, typeContext, node);
   }
 
   @override
@@ -431,8 +450,8 @@
         typeParameters: freshTypeParameters.freshTypeParameters,
         requiredParameterCount: resultType.requiredParameterCount);
     ExpressionInferenceResult inferredResult =
-        inferrer.instantiateTearOff(resultType, typeContext, node);
-    return inferrer.ensureAssignableResult(typeContext, inferredResult);
+        instantiateTearOff(resultType, typeContext, node);
+    return ensureAssignableResult(typeContext, inferredResult);
   }
 
   @override
@@ -504,7 +523,7 @@
       InvalidExpression node, DartType typeContext) {
     if (node.expression != null) {
       ExpressionInferenceResult result = inferExpression(
-          node.expression!, typeContext, !inferrer.isTopLevel,
+          node.expression!, typeContext, !isTopLevel,
           isVoidAllowed: true);
       node.expression = result.expression..parent = node;
     }
@@ -520,7 +539,7 @@
     Expression operand = operandResult.expression;
     DartType operandType = operandResult.inferredType;
     if (operandType is! FunctionType) {
-      ObjectAccessTarget callMember = inferrer.findInterfaceMember(
+      ObjectAccessTarget callMember = findInterfaceMember(
           operandType, callName, operand.fileOffset,
           callSiteAccessKind: CallSiteAccessKind.getterInvocation,
           includeExtensionMethods: true);
@@ -528,7 +547,7 @@
         case ObjectAccessTargetKind.instanceMember:
           Member? target = callMember.member;
           if (target is Procedure && target.kind == ProcedureKind.Method) {
-            operandType = inferrer.getGetterType(callMember, operandType);
+            operandType = getGetterType(callMember, operandType);
             operand = new InstanceTearOff(
                 InstanceAccessKind.Instance, operand, callName,
                 interfaceTarget: target, resultType: operandType)
@@ -538,7 +557,7 @@
         case ObjectAccessTargetKind.extensionMember:
           if (callMember.tearoffTarget != null &&
               callMember.extensionMethodKind == ProcedureKind.Method) {
-            operandType = inferrer.getGetterType(callMember, operandType);
+            operandType = getGetterType(callMember, operandType);
             operand = new StaticInvocation(
                 callMember.tearoffTarget as Procedure,
                 new Arguments(<Expression>[operand],
@@ -565,16 +584,16 @@
     DartType resultType = const InvalidType();
     if (operandType is FunctionType) {
       if (operandType.typeParameters.length == node.typeArguments.length) {
-        if (!inferrer.isTopLevel) {
-          inferrer.checkBoundsInInstantiation(
+        if (!isTopLevel) {
+          checkBoundsInInstantiation(
               operandType, node.typeArguments, node.fileOffset,
               inferred: false);
         }
         if (operandType.isPotentiallyNullable) {
-          if (!inferrer.isTopLevel) {
-            result = inferrer.helper.buildProblem(
+          if (!isTopLevel) {
+            result = helper.buildProblem(
                 templateInstantiationNullableGenericFunctionType.withArguments(
-                    operandType, inferrer.isNonNullableByDefault),
+                    operandType, isNonNullableByDefault),
                 node.fileOffset,
                 noLength);
           }
@@ -584,16 +603,16 @@
               .substituteType(operandType.withoutTypeParameters);
         }
       } else {
-        if (!inferrer.isTopLevel) {
+        if (!isTopLevel) {
           if (operandType.typeParameters.isEmpty) {
-            result = inferrer.helper.buildProblem(
+            result = helper.buildProblem(
                 templateInstantiationNonGenericFunctionType.withArguments(
-                    operandType, inferrer.isNonNullableByDefault),
+                    operandType, isNonNullableByDefault),
                 node.fileOffset,
                 noLength);
           } else if (operandType.typeParameters.length >
               node.typeArguments.length) {
-            result = inferrer.helper.buildProblem(
+            result = helper.buildProblem(
                 templateInstantiationTooFewArguments.withArguments(
                     operandType.typeParameters.length,
                     node.typeArguments.length),
@@ -601,7 +620,7 @@
                 noLength);
           } else if (operandType.typeParameters.length <
               node.typeArguments.length) {
-            result = inferrer.helper.buildProblem(
+            result = helper.buildProblem(
                 templateInstantiationTooManyArguments.withArguments(
                     operandType.typeParameters.length,
                     node.typeArguments.length),
@@ -611,10 +630,10 @@
         }
       }
     } else if (operandType is! InvalidType) {
-      if (!inferrer.isTopLevel) {
-        result = inferrer.helper.buildProblem(
+      if (!isTopLevel) {
+        result = helper.buildProblem(
             templateInstantiationNonGenericFunctionType.withArguments(
-                operandType, inferrer.isNonNullableByDefault),
+                operandType, isNonNullableByDefault),
             node.fileOffset,
             noLength);
       }
@@ -626,18 +645,17 @@
   ExpressionInferenceResult visitIntLiteral(
       IntLiteral node, DartType typeContext) {
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.intRawType(inferrer.libraryBuilder.nonNullable),
-        node);
+        coreTypes.intRawType(libraryBuilder.nonNullable), node);
   }
 
   @override
   ExpressionInferenceResult visitAsExpression(
       AsExpression node, DartType typeContext) {
     ExpressionInferenceResult operandResult = inferExpression(
-        node.operand, const UnknownType(), !inferrer.isTopLevel,
+        node.operand, const UnknownType(), !isTopLevel,
         isVoidAllowed: true);
     node.operand = operandResult.expression..parent = node;
-    inferrer.flowAnalysis.asExpression_end(node.operand, node.type);
+    flowAnalysis.asExpression_end(node.operand, node.type);
     return new ExpressionInferenceResult(node.type, node);
   }
 
@@ -652,39 +670,38 @@
 
   @override
   StatementInferenceResult visitAssertStatement(AssertStatement node) {
-    inferrer.flowAnalysis.assert_begin();
+    flowAnalysis.assert_begin();
     InterfaceType expectedType =
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+        coreTypes.boolRawType(libraryBuilder.nonNullable);
     ExpressionInferenceResult conditionResult = inferExpression(
-        node.condition, expectedType, !inferrer.isTopLevel,
+        node.condition, expectedType, !isTopLevel,
         isVoidAllowed: true);
 
-    Expression condition = inferrer
-        .ensureAssignableResult(expectedType, conditionResult)
-        .expression;
+    Expression condition =
+        ensureAssignableResult(expectedType, conditionResult).expression;
     node.condition = condition..parent = node;
-    inferrer.flowAnalysis.assert_afterCondition(node.condition);
+    flowAnalysis.assert_afterCondition(node.condition);
     if (node.message != null) {
       ExpressionInferenceResult messageResult = inferExpression(
-          node.message!, const UnknownType(), !inferrer.isTopLevel,
+          node.message!, const UnknownType(), !isTopLevel,
           isVoidAllowed: true);
       node.message = messageResult.expression..parent = node;
     }
-    inferrer.flowAnalysis.assert_end();
+    flowAnalysis.assert_end();
     return const StatementInferenceResult();
   }
 
   @override
   ExpressionInferenceResult visitAwaitExpression(
       AwaitExpression node, DartType typeContext) {
-    if (!inferrer.typeSchemaEnvironment.isEmptyContext(typeContext)) {
-      typeContext = inferrer.wrapFutureOrType(typeContext);
+    if (!typeSchemaEnvironment.isEmptyContext(typeContext)) {
+      typeContext = wrapFutureOrType(typeContext);
     }
     ExpressionInferenceResult operandResult = inferExpression(
         node.operand, typeContext, true,
-        isVoidAllowed: !inferrer.isNonNullableByDefault);
+        isVoidAllowed: !isNonNullableByDefault);
     DartType inferredType =
-        inferrer.typeSchemaEnvironment.flatten(operandResult.inferredType);
+        typeSchemaEnvironment.flatten(operandResult.inferredType);
     node.operand = operandResult.expression..parent = node;
     return new ExpressionInferenceResult(inferredType, node);
   }
@@ -713,11 +730,11 @@
 
   @override
   StatementInferenceResult visitBlock(Block node) {
-    inferrer.registerIfUnreachableForTesting(node);
+    registerIfUnreachableForTesting(node);
     List<Statement>? result = _visitStatements<Statement>(node.statements);
     if (result != null) {
       Block block = new Block(result)..fileOffset = node.fileOffset;
-      inferrer.libraryBuilder.loader.dataForTesting?.registerAlias(node, block);
+      libraryBuilder.loader.dataForTesting?.registerAlias(node, block);
       return new StatementInferenceResult.single(block);
     } else {
       return const StatementInferenceResult();
@@ -727,10 +744,9 @@
   @override
   ExpressionInferenceResult visitBoolLiteral(
       BoolLiteral node, DartType typeContext) {
-    inferrer.flowAnalysis.booleanLiteral(node, node.value);
+    flowAnalysis.booleanLiteral(node, node.value);
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable),
-        node);
+        coreTypes.boolRawType(libraryBuilder.nonNullable), node);
   }
 
   @override
@@ -739,9 +755,9 @@
     // TODO(johnniwinther): Refactor break/continue encoding.
     assert(node.targetStatement != null);
     if (node.isContinue) {
-      inferrer.flowAnalysis.handleContinue(node.targetStatement!);
+      flowAnalysis.handleContinue(node.targetStatement!);
     } else {
-      inferrer.flowAnalysis.handleBreak(node.targetStatement!);
+      flowAnalysis.handleBreak(node.targetStatement!);
     }
     return const StatementInferenceResult();
   }
@@ -759,14 +775,14 @@
     node.variable.type = result.inferredType;
     NullAwareGuard? nullAwareGuard;
     if (node.isNullAware) {
-      nullAwareGuard = inferrer.createNullAwareGuard(node.variable);
+      nullAwareGuard = createNullAwareGuard(node.variable);
     }
 
     List<ExpressionInferenceResult> expressionResults =
         <ExpressionInferenceResult>[];
     for (Expression expression in node.expressions) {
       expressionResults.add(inferExpression(
-          expression, const UnknownType(), !inferrer.isTopLevel,
+          expression, const UnknownType(), !isTopLevel,
           isVoidAllowed: true, forEffect: true));
     }
     List<Statement> body = [];
@@ -811,34 +827,33 @@
   @override
   ExpressionInferenceResult visitConditionalExpression(
       ConditionalExpression node, DartType typeContext) {
-    inferrer.flowAnalysis.conditional_conditionBegin();
+    flowAnalysis.conditional_conditionBegin();
     InterfaceType expectedType =
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+        coreTypes.boolRawType(libraryBuilder.nonNullable);
     ExpressionInferenceResult conditionResult = inferExpression(
-        node.condition, expectedType, !inferrer.isTopLevel,
+        node.condition, expectedType, !isTopLevel,
         isVoidAllowed: true);
-    Expression condition = inferrer
-        .ensureAssignableResult(expectedType, conditionResult)
-        .expression;
+    Expression condition =
+        ensureAssignableResult(expectedType, conditionResult).expression;
     node.condition = condition..parent = node;
-    inferrer.flowAnalysis.conditional_thenBegin(node.condition, node);
-    bool isThenReachable = inferrer.flowAnalysis.isReachable;
+    flowAnalysis.conditional_thenBegin(node.condition, node);
+    bool isThenReachable = flowAnalysis.isReachable;
     ExpressionInferenceResult thenResult =
         inferExpression(node.then, typeContext, true, isVoidAllowed: true);
     node.then = thenResult.expression..parent = node;
-    inferrer.registerIfUnreachableForTesting(node.then,
-        isReachable: isThenReachable);
-    inferrer.flowAnalysis.conditional_elseBegin(node.then);
-    bool isOtherwiseReachable = inferrer.flowAnalysis.isReachable;
+    registerIfUnreachableForTesting(node.then, isReachable: isThenReachable);
+    flowAnalysis.conditional_elseBegin(node.then);
+    bool isOtherwiseReachable = flowAnalysis.isReachable;
     ExpressionInferenceResult otherwiseResult =
         inferExpression(node.otherwise, typeContext, true, isVoidAllowed: true);
     node.otherwise = otherwiseResult.expression..parent = node;
-    inferrer.registerIfUnreachableForTesting(node.otherwise,
+    registerIfUnreachableForTesting(node.otherwise,
         isReachable: isOtherwiseReachable);
-    inferrer.flowAnalysis.conditional_end(node, node.otherwise);
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(thenResult.inferredType,
-            otherwiseResult.inferredType, inferrer.libraryBuilder.library);
+    flowAnalysis.conditional_end(node, node.otherwise);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        thenResult.inferredType,
+        otherwiseResult.inferredType,
+        libraryBuilder.library);
     node.staticType = inferredType;
     return new ExpressionInferenceResult(inferredType, node);
   }
@@ -846,23 +861,18 @@
   @override
   ExpressionInferenceResult visitConstructorInvocation(
       ConstructorInvocation node, DartType typeContext) {
-    inferrer.inferConstructorParameterTypes(node.target);
+    inferConstructorParameterTypes(node.target);
     bool hadExplicitTypeArguments = hasExplicitTypeArguments(node.arguments);
     FunctionType functionType = node.target.function
-        .computeThisFunctionType(inferrer.libraryBuilder.nonNullable);
-    InvocationInferenceResult result = inferrer.inferInvocation(
-        this,
-        typeContext,
-        node.fileOffset,
-        functionType,
-        node.arguments as ArgumentsImpl,
-        isConst: node.isConst,
-        staticTarget: node.target);
-    if (!inferrer.isTopLevel) {
-      SourceLibraryBuilder library = inferrer.libraryBuilder;
+        .computeThisFunctionType(libraryBuilder.nonNullable);
+    InvocationInferenceResult result = inferInvocation(this, typeContext,
+        node.fileOffset, functionType, node.arguments as ArgumentsImpl,
+        isConst: node.isConst, staticTarget: node.target);
+    if (!isTopLevel) {
+      SourceLibraryBuilder library = libraryBuilder;
       if (!hadExplicitTypeArguments) {
         library.checkBoundsInConstructorInvocation(
-            node, inferrer.typeSchemaEnvironment, inferrer.helper.uri,
+            node, typeSchemaEnvironment, helper.uri,
             inferred: true);
       }
     }
@@ -873,7 +883,7 @@
   @override
   StatementInferenceResult visitContinueSwitchStatement(
       ContinueSwitchStatement node) {
-    inferrer.flowAnalysis.handleContinue(node.target.body);
+    flowAnalysis.handleContinue(node.target.body);
     return const StatementInferenceResult();
   }
 
@@ -881,29 +891,20 @@
       ExtensionTearOff node, DartType typeContext) {
     // ignore: unnecessary_null_comparison
     FunctionType calleeType = node.target != null
-        ? node.target.function
-            .computeFunctionType(inferrer.libraryBuilder.nonNullable)
-        : new FunctionType(
-            [], const DynamicType(), inferrer.libraryBuilder.nonNullable);
+        ? node.target.function.computeFunctionType(libraryBuilder.nonNullable)
+        : new FunctionType([], const DynamicType(), libraryBuilder.nonNullable);
     TypeArgumentsInfo typeArgumentsInfo = getTypeArgumentsInfo(node.arguments);
-    InvocationInferenceResult result = inferrer.inferInvocation(
-        this,
-        typeContext,
-        node.fileOffset,
-        calleeType,
-        node.arguments as ArgumentsImpl,
+    InvocationInferenceResult result = inferInvocation(this, typeContext,
+        node.fileOffset, calleeType, node.arguments as ArgumentsImpl,
         staticTarget: node.target);
     StaticInvocation replacement =
         new StaticInvocation(node.target, node.arguments);
     // ignore: unnecessary_null_comparison
-    if (!inferrer.isTopLevel && node.target != null) {
-      inferrer.libraryBuilder.checkBoundsInStaticInvocation(
-          replacement,
-          inferrer.typeSchemaEnvironment,
-          inferrer.helper.uri,
-          typeArgumentsInfo);
+    if (!isTopLevel && node.target != null) {
+      libraryBuilder.checkBoundsInStaticInvocation(
+          replacement, typeSchemaEnvironment, helper.uri, typeArgumentsInfo);
     }
-    return inferrer.instantiateTearOff(
+    return instantiateTearOff(
         result.inferredType, typeContext, result.applyResult(replacement));
   }
 
@@ -913,27 +914,26 @@
         node.receiver, const UnknownType(), true,
         isVoidAllowed: false);
 
-    List<DartType> extensionTypeArguments =
-        inferrer.computeExtensionTypeArgument(node.extension,
-            node.explicitTypeArguments, receiverResult.inferredType);
+    List<DartType> extensionTypeArguments = computeExtensionTypeArgument(
+        node.extension,
+        node.explicitTypeArguments,
+        receiverResult.inferredType);
 
-    DartType receiverType = inferrer.getExtensionReceiverType(
-        node.extension, extensionTypeArguments);
+    DartType receiverType =
+        getExtensionReceiverType(node.extension, extensionTypeArguments);
 
-    Expression receiver = inferrer
-        .ensureAssignableResult(receiverType, receiverResult)
-        .expression;
+    Expression receiver =
+        ensureAssignableResult(receiverType, receiverResult).expression;
 
     ObjectAccessTarget target = new ExtensionAccessTarget(
         node.target, null, ProcedureKind.Setter, extensionTypeArguments);
 
-    DartType valueType =
-        inferrer.getSetterType(target, receiverResult.inferredType);
+    DartType valueType = getSetterType(target, receiverResult.inferredType);
 
     ExpressionInferenceResult valueResult = inferExpression(
         node.value, const UnknownType(), true,
         isVoidAllowed: false);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
 
     VariableDeclaration? valueVariable;
@@ -983,16 +983,16 @@
         node.receiver, const UnknownType(), true,
         isVoidAllowed: false);
 
-    List<DartType> extensionTypeArguments =
-        inferrer.computeExtensionTypeArgument(node.extension,
-            node.explicitTypeArguments, receiverResult.inferredType);
+    List<DartType> extensionTypeArguments = computeExtensionTypeArgument(
+        node.extension,
+        node.explicitTypeArguments,
+        receiverResult.inferredType);
 
-    DartType receiverType = inferrer.getExtensionReceiverType(
-        node.extension, extensionTypeArguments);
+    DartType receiverType =
+        getExtensionReceiverType(node.extension, extensionTypeArguments);
 
-    Expression receiver = inferrer
-        .ensureAssignableResult(receiverType, receiverResult)
-        .expression;
+    Expression receiver =
+        ensureAssignableResult(receiverType, receiverResult).expression;
 
     VariableDeclaration? receiverVariable;
     Expression readReceiver;
@@ -1011,11 +1011,11 @@
         : new ExtensionAccessTarget(
             node.getter!, null, ProcedureKind.Getter, extensionTypeArguments);
 
-    DartType readType = inferrer.getGetterType(readTarget, receiverType);
+    DartType readType = getGetterType(readTarget, receiverType);
 
     Expression read;
     if (readTarget.isMissing) {
-      read = inferrer.createMissingPropertyGet(
+      read = createMissingPropertyGet(
           node.readOffset, readReceiver, readType, node.propertyName);
     } else {
       assert(readTarget.isExtensionMember);
@@ -1033,7 +1033,7 @@
         : new ExtensionAccessTarget(
             node.setter!, null, ProcedureKind.Setter, extensionTypeArguments);
 
-    DartType valueType = inferrer.getSetterType(writeTarget, receiverType);
+    DartType valueType = getSetterType(writeTarget, receiverType);
 
     ExpressionInferenceResult binaryResult = _computeBinaryExpression(
         node.binaryOffset,
@@ -1044,8 +1044,8 @@
         node.rhs,
         null);
 
-    binaryResult = inferrer.ensureAssignableResult(valueType, binaryResult,
-        isVoidAllowed: true);
+    binaryResult =
+        ensureAssignableResult(valueType, binaryResult, isVoidAllowed: true);
     Expression value = binaryResult.expression;
 
     VariableDeclaration? valueVariable;
@@ -1058,7 +1058,7 @@
 
     Expression write;
     if (writeTarget.isMissing) {
-      write = inferrer.createMissingPropertySet(
+      write = createMissingPropertySet(
           node.writeOffset, writeReceiver, readType, node.propertyName, value,
           forEffect: node.forEffect);
     } else {
@@ -1106,21 +1106,20 @@
 
   @override
   StatementInferenceResult visitDoStatement(DoStatement node) {
-    inferrer.flowAnalysis.doStatement_bodyBegin(node);
+    flowAnalysis.doStatement_bodyBegin(node);
     StatementInferenceResult bodyResult = inferStatement(node.body);
     if (bodyResult.hasChanged) {
       node.body = bodyResult.statement..parent = node;
     }
-    inferrer.flowAnalysis.doStatement_conditionBegin();
-    InterfaceType boolType =
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+    flowAnalysis.doStatement_conditionBegin();
+    InterfaceType boolType = coreTypes.boolRawType(libraryBuilder.nonNullable);
     ExpressionInferenceResult conditionResult = inferExpression(
-        node.condition, boolType, !inferrer.isTopLevel,
+        node.condition, boolType, !isTopLevel,
         isVoidAllowed: true);
     Expression condition =
-        inferrer.ensureAssignableResult(boolType, conditionResult).expression;
+        ensureAssignableResult(boolType, conditionResult).expression;
     node.condition = condition..parent = node;
-    inferrer.flowAnalysis.doStatement_end(condition);
+    flowAnalysis.doStatement_end(condition);
     return const StatementInferenceResult();
   }
 
@@ -1128,8 +1127,7 @@
   ExpressionInferenceResult visitDoubleLiteral(
       DoubleLiteral node, DartType typeContext) {
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.doubleRawType(inferrer.libraryBuilder.nonNullable),
-        node);
+        coreTypes.doubleRawType(libraryBuilder.nonNullable), node);
   }
 
   @override
@@ -1141,7 +1139,7 @@
   @override
   StatementInferenceResult visitExpressionStatement(ExpressionStatement node) {
     ExpressionInferenceResult result = inferExpression(
-        node.expression, const UnknownType(), !inferrer.isTopLevel,
+        node.expression, const UnknownType(), !isTopLevel,
         isVoidAllowed: true, forEffect: true);
     node.expression = result.expression..parent = node;
     return const StatementInferenceResult();
@@ -1152,28 +1150,23 @@
     bool hadExplicitTypeArguments = hasExplicitTypeArguments(node.arguments);
 
     FunctionType functionType = node.target.function
-        .computeThisFunctionType(inferrer.libraryBuilder.nonNullable);
+        .computeThisFunctionType(libraryBuilder.nonNullable);
 
-    InvocationInferenceResult result = inferrer.inferInvocation(
-        this,
-        typeContext,
-        node.fileOffset,
-        functionType,
-        node.arguments as ArgumentsImpl,
-        isConst: node.isConst,
-        staticTarget: node.target);
+    InvocationInferenceResult result = inferInvocation(this, typeContext,
+        node.fileOffset, functionType, node.arguments as ArgumentsImpl,
+        isConst: node.isConst, staticTarget: node.target);
     node.hasBeenInferred = true;
     Expression resultNode = node;
-    if (!inferrer.isTopLevel) {
-      SourceLibraryBuilder library = inferrer.libraryBuilder;
+    if (!isTopLevel) {
+      SourceLibraryBuilder library = libraryBuilder;
       if (!hadExplicitTypeArguments) {
         library.checkBoundsInFactoryInvocation(
-            node, inferrer.typeSchemaEnvironment, inferrer.helper.uri,
+            node, typeSchemaEnvironment, helper.uri,
             inferred: true);
       }
-      if (inferrer.isNonNullableByDefault) {
-        if (node.target == inferrer.coreTypes.listDefaultConstructor) {
-          resultNode = inferrer.helper.wrapInProblem(node,
+      if (isNonNullableByDefault) {
+        if (node.target == coreTypes.listDefaultConstructor) {
+          resultNode = helper.wrapInProblem(node,
               messageDefaultListConstructorError, node.fileOffset, noLength);
         }
       }
@@ -1187,23 +1180,17 @@
     assert(getExplicitTypeArguments(node.arguments) == null);
     Typedef typedef = node.typeAliasBuilder.typedef;
     FunctionType calleeType = node.target.function
-        .computeAliasedConstructorFunctionType(
-            typedef, inferrer.libraryBuilder.library);
+        .computeAliasedConstructorFunctionType(typedef, libraryBuilder.library);
     calleeType = replaceReturnType(calleeType, calleeType.returnType.unalias);
-    InvocationInferenceResult result = inferrer.inferInvocation(
-        this,
-        typeContext,
-        node.fileOffset,
-        calleeType,
-        node.arguments as ArgumentsImpl,
-        isConst: node.isConst,
-        staticTarget: node.target);
+    InvocationInferenceResult result = inferInvocation(this, typeContext,
+        node.fileOffset, calleeType, node.arguments as ArgumentsImpl,
+        isConst: node.isConst, staticTarget: node.target);
     node.hasBeenInferred = true;
     Expression resultNode = node;
-    if (!inferrer.isTopLevel) {
-      if (inferrer.isNonNullableByDefault) {
-        if (node.target == inferrer.coreTypes.listDefaultConstructor) {
-          resultNode = inferrer.helper.wrapInProblem(node,
+    if (!isTopLevel) {
+      if (isNonNullableByDefault) {
+        if (node.target == coreTypes.listDefaultConstructor) {
+          resultNode = helper.wrapInProblem(node,
               messageDefaultListConstructorError, node.fileOffset, noLength);
         }
       }
@@ -1217,23 +1204,17 @@
     assert(getExplicitTypeArguments(node.arguments) == null);
     Typedef typedef = node.typeAliasBuilder.typedef;
     FunctionType calleeType = node.target.function
-        .computeAliasedFactoryFunctionType(
-            typedef, inferrer.libraryBuilder.library);
+        .computeAliasedFactoryFunctionType(typedef, libraryBuilder.library);
     calleeType = replaceReturnType(calleeType, calleeType.returnType.unalias);
-    InvocationInferenceResult result = inferrer.inferInvocation(
-        this,
-        typeContext,
-        node.fileOffset,
-        calleeType,
-        node.arguments as ArgumentsImpl,
-        isConst: node.isConst,
-        staticTarget: node.target);
+    InvocationInferenceResult result = inferInvocation(this, typeContext,
+        node.fileOffset, calleeType, node.arguments as ArgumentsImpl,
+        isConst: node.isConst, staticTarget: node.target);
     node.hasBeenInferred = true;
     Expression resultNode = node;
-    if (!inferrer.isTopLevel) {
-      if (inferrer.isNonNullableByDefault) {
-        if (node.target == inferrer.coreTypes.listDefaultConstructor) {
-          resultNode = inferrer.helper.wrapInProblem(node,
+    if (!isTopLevel) {
+      if (isNonNullableByDefault) {
+        if (node.target == coreTypes.listDefaultConstructor) {
+          resultNode = helper.wrapInProblem(node,
               messageDefaultListConstructorError, node.fileOffset, noLength);
         }
       }
@@ -1246,8 +1227,8 @@
   InitializerInferenceResult visitFieldInitializer(FieldInitializer node) {
     ExpressionInferenceResult initializerResult =
         inferExpression(node.value, node.field.type, true);
-    Expression initializer = inferrer
-        .ensureAssignableResult(node.field.type, initializerResult,
+    Expression initializer = ensureAssignableResult(
+            node.field.type, initializerResult,
             fileOffset: node.fileOffset)
         .expression;
     node.value = initializer..parent = node;
@@ -1262,7 +1243,7 @@
       {bool isAsync: false}) {
     DartType elementType;
     bool typeNeeded = false;
-    bool typeChecksNeeded = !inferrer.isTopLevel;
+    bool typeChecksNeeded = !isTopLevel;
     if (variable is VariableDeclarationImpl && variable.isImplicitlyTyped) {
       typeNeeded = true;
       elementType = const UnknownType();
@@ -1275,25 +1256,22 @@
         isAsync: isAsync);
     DartType inferredType = iterableResult.inferredType;
     if (typeNeeded) {
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          variable.fileOffset,
-          'type',
-          new InstrumentationValueForType(inferredType));
+      instrumentation?.record(uriForInstrumentation, variable.fileOffset,
+          'type', new InstrumentationValueForType(inferredType));
       variable.type = inferredType;
     }
 
     // This is matched by the call to [forEach_end] in
     // [inferElement], [inferMapEntry] or [inferForInStatement].
-    inferrer.flowAnalysis.declare(variable, true);
-    inferrer.flowAnalysis.forEach_bodyBegin(node);
+    flowAnalysis.declare(variable, true);
+    flowAnalysis.forEach_bodyBegin(node);
 
     VariableDeclaration tempVariable =
         new VariableDeclaration(null, type: inferredType, isFinal: true);
     VariableGet variableGet = new VariableGet(tempVariable)
       ..fileOffset = variable.fileOffset;
     TreeNode parent = variable.parent!;
-    Expression implicitDowncast = inferrer.ensureAssignable(
+    Expression implicitDowncast = ensureAssignable(
         variable.type, inferredType, variableGet,
         isVoidAllowed: true,
         fileOffset: parent.fileOffset,
@@ -1327,20 +1305,18 @@
   ExpressionInferenceResult inferForInIterable(
       Expression iterable, DartType elementType, bool typeNeeded,
       {bool isAsync: false}) {
-    Class iterableClass = isAsync
-        ? inferrer.coreTypes.streamClass
-        : inferrer.coreTypes.iterableClass;
-    DartType context = inferrer.wrapType(
-        elementType, iterableClass, inferrer.libraryBuilder.nonNullable);
+    Class iterableClass =
+        isAsync ? coreTypes.streamClass : coreTypes.iterableClass;
+    DartType context =
+        wrapType(elementType, iterableClass, libraryBuilder.nonNullable);
     ExpressionInferenceResult iterableResult =
         inferExpression(iterable, context, typeNeeded, isVoidAllowed: false);
     DartType iterableType = iterableResult.inferredType;
     iterable = iterableResult.expression;
-    DartType inferredExpressionType =
-        inferrer.resolveTypeParameter(iterableType);
-    iterable = inferrer.ensureAssignable(
-        inferrer.wrapType(const DynamicType(), iterableClass,
-            inferrer.libraryBuilder.nonNullable),
+    DartType inferredExpressionType = resolveTypeParameter(iterableType);
+    iterable = ensureAssignable(
+        wrapType(
+            const DynamicType(), iterableClass, libraryBuilder.nonNullable),
         inferredExpressionType,
         iterable,
         errorTemplate: templateForInLoopTypeNotIterable,
@@ -1353,8 +1329,8 @@
       if (inferredExpressionType is InterfaceType) {
         // TODO(johnniwinther): Should we use the type of
         //  `iterable.iterator.current` instead?
-        List<DartType>? supertypeArguments = inferrer.classHierarchy
-            .getTypeArgumentsAsInstanceOf(
+        List<DartType>? supertypeArguments =
+            classHierarchy.getTypeArgumentsAsInstanceOf(
                 inferredExpressionType, iterableClass);
         if (supertypeArguments != null) {
           inferredType = supertypeArguments[0];
@@ -1400,7 +1376,7 @@
       required bool hasProblem}) {
     // ignore: unnecessary_null_comparison
     assert(hasProblem != null);
-    bool typeChecksNeeded = !inferrer.isTopLevel;
+    bool typeChecksNeeded = !isTopLevel;
     ForInVariable forInVariable =
         computeForInVariable(syntheticAssignment, hasProblem);
     DartType elementType = forInVariable.computeElementType(this);
@@ -1413,10 +1389,10 @@
     }
     // This is matched by the call to [forEach_end] in
     // [inferElement], [inferMapEntry] or [inferForInStatement].
-    inferrer.flowAnalysis.forEach_bodyBegin(node);
+    flowAnalysis.forEach_bodyBegin(node);
     syntheticAssignment = forInVariable.inferAssignment(this, inferredType);
     if (syntheticAssignment is VariableSet) {
-      inferrer.flowAnalysis.write(node, variable, inferredType, null);
+      flowAnalysis.write(node, variable, inferredType, null);
     }
     if (expressionEffects != null) {
       StatementInferenceResult result = inferStatement(expressionEffects);
@@ -1438,7 +1414,7 @@
 
     // This is matched by the call to [forEach_bodyBegin] in
     // [handleForInWithoutVariable] or [handleForInDeclaringVariable].
-    inferrer.flowAnalysis.forEach_end();
+    flowAnalysis.forEach_end();
 
     Statement body = bodyResult.hasChanged ? bodyResult.statement : node.body;
     if (result.expressionSideEffects != null) {
@@ -1465,7 +1441,7 @@
 
     // This is matched by the call to [forEach_bodyBegin] in
     // [handleForInWithoutVariable] or [handleForInDeclaringVariable].
-    inferrer.flowAnalysis.forEach_end();
+    flowAnalysis.forEach_end();
 
     Statement body = bodyResult.hasChanged ? bodyResult.statement : node.body;
     if (result.expressionSideEffects != null) {
@@ -1480,8 +1456,7 @@
         isAsync: node.isAsync)
       ..fileOffset = node.fileOffset
       ..bodyOffset = node.bodyOffset;
-    inferrer.libraryBuilder.loader.dataForTesting
-        ?.registerAlias(node, replacement);
+    libraryBuilder.loader.dataForTesting?.registerAlias(node, replacement);
     return new StatementInferenceResult.single(replacement);
   }
 
@@ -1522,89 +1497,90 @@
       node.variables.addAll(variables);
       setParents(variables, node);
     }
-    inferrer.flowAnalysis.for_conditionBegin(node);
+    flowAnalysis.for_conditionBegin(node);
     if (node.condition != null) {
       InterfaceType expectedType =
-          inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+          coreTypes.boolRawType(libraryBuilder.nonNullable);
       ExpressionInferenceResult conditionResult = inferExpression(
-          node.condition!, expectedType, !inferrer.isTopLevel,
+          node.condition!, expectedType, !isTopLevel,
           isVoidAllowed: true);
-      Expression condition = inferrer
-          .ensureAssignableResult(expectedType, conditionResult)
-          .expression;
+      Expression condition =
+          ensureAssignableResult(expectedType, conditionResult).expression;
       node.condition = condition..parent = node;
     }
 
-    inferrer.flowAnalysis.for_bodyBegin(node, node.condition);
+    flowAnalysis.for_bodyBegin(node, node.condition);
     StatementInferenceResult bodyResult = inferStatement(node.body);
     if (bodyResult.hasChanged) {
       node.body = bodyResult.statement..parent = node;
     }
-    inferrer.flowAnalysis.for_updaterBegin();
+    flowAnalysis.for_updaterBegin();
     for (int index = 0; index < node.updates.length; index++) {
       ExpressionInferenceResult updateResult = inferExpression(
-          node.updates[index], const UnknownType(), !inferrer.isTopLevel,
+          node.updates[index], const UnknownType(), !isTopLevel,
           isVoidAllowed: true);
       node.updates[index] = updateResult.expression..parent = node;
     }
-    inferrer.flowAnalysis.for_end();
+    flowAnalysis.for_end();
     return const StatementInferenceResult();
   }
 
   FunctionType visitFunctionNode(FunctionNode node, DartType? typeContext,
       DartType? returnContext, int returnTypeInstrumentationOffset) {
-    return inferrer.inferLocalFunction(this, node, typeContext,
+    return inferLocalFunction(this, node, typeContext,
         returnTypeInstrumentationOffset, returnContext);
   }
 
   @override
   StatementInferenceResult visitFunctionDeclaration(
       covariant FunctionDeclarationImpl node) {
-    inferrer.flowAnalysis.declare(node.variable, true);
-    inferrer.flowAnalysis.functionExpression_begin(node);
-    inferrer.inferMetadataKeepingHelper(
-        this, node.variable, node.variable.annotations);
+    flowAnalysis.declare(node.variable, true);
+    flowAnalysis.functionExpression_begin(node);
+    inferMetadata(this, node.variable, node.variable.annotations);
     DartType? returnContext =
         node.hasImplicitReturnType ? null : node.function.returnType;
     FunctionType inferredType =
         visitFunctionNode(node.function, null, returnContext, node.fileOffset);
-    if (inferrer.dataForTesting != null && node.hasImplicitReturnType) {
-      inferrer.dataForTesting!.typeInferenceResult.inferredVariableTypes[node] =
+    if (dataForTesting != null && node.hasImplicitReturnType) {
+      dataForTesting!.typeInferenceResult.inferredVariableTypes[node] =
           inferredType.returnType;
     }
     node.variable.type = inferredType;
-    inferrer.flowAnalysis.functionExpression_end();
+    flowAnalysis.functionExpression_end();
     return const StatementInferenceResult();
   }
 
   @override
   ExpressionInferenceResult visitFunctionExpression(
       FunctionExpression node, DartType typeContext) {
-    inferrer.flowAnalysis.functionExpression_begin(node);
+    flowAnalysis.functionExpression_begin(node);
     FunctionType inferredType =
         visitFunctionNode(node.function, typeContext, null, node.fileOffset);
-    if (inferrer.dataForTesting != null) {
-      inferrer.dataForTesting!.typeInferenceResult.inferredVariableTypes[node] =
+    if (dataForTesting != null) {
+      dataForTesting!.typeInferenceResult.inferredVariableTypes[node] =
           inferredType.returnType;
     }
-    inferrer.flowAnalysis.functionExpression_end();
+    flowAnalysis.functionExpression_end();
     return new ExpressionInferenceResult(inferredType, node);
   }
 
   InitializerInferenceResult visitInvalidSuperInitializerJudgment(
       InvalidSuperInitializerJudgment node) {
     Substitution substitution = Substitution.fromSupertype(
-        inferrer.classHierarchy.getClassAsInstanceOf(
-            inferrer.thisType!.classNode, node.target.enclosingClass)!);
+        classHierarchy.getClassAsInstanceOf(
+            thisType!.classNode, node.target.enclosingClass)!);
     FunctionType functionType = replaceReturnType(
         substitution.substituteType(node.target.function
-            .computeThisFunctionType(inferrer.libraryBuilder.nonNullable)
+            .computeThisFunctionType(libraryBuilder.nonNullable)
             .withoutTypeParameters) as FunctionType,
-        inferrer.thisType!);
-    InvocationInferenceResult invocationInferenceResult =
-        inferrer.inferInvocation(this, const UnknownType(), node.fileOffset,
-            functionType, node.argumentsJudgment,
-            skipTypeArgumentInference: true);
+        thisType!);
+    InvocationInferenceResult invocationInferenceResult = inferInvocation(
+        this,
+        const UnknownType(),
+        node.fileOffset,
+        functionType,
+        node.argumentsJudgment,
+        skipTypeArgumentInference: true);
     return new InitializerInferenceResult.fromInvocationInferenceResult(
         invocationInferenceResult);
   }
@@ -1614,7 +1590,7 @@
     // To infer `e0 ?? e1` in context K:
     // - Infer e0 in context K to get T0
     ExpressionInferenceResult lhsResult = inferExpression(
-        node.left, inferrer.computeNullable(typeContext), true,
+        node.left, computeNullable(typeContext), true,
         isVoidAllowed: false);
     reportNonNullableInNullAwareWarningIfNeeded(
         lhsResult.inferredType, "??", lhsResult.expression.fileOffset);
@@ -1622,8 +1598,7 @@
     // This ends any shorting in `node.left`.
     Expression left = lhsResult.expression;
 
-    inferrer.flowAnalysis
-        .ifNullExpression_rightBegin(node.left, lhsResult.inferredType);
+    flowAnalysis.ifNullExpression_rightBegin(node.left, lhsResult.inferredType);
 
     // - Let J = T0 if K is `?` else K.
     // - Infer e1 in context J to get T1
@@ -1635,26 +1610,25 @@
       rhsResult =
           inferExpression(node.right, typeContext, true, isVoidAllowed: true);
     }
-    inferrer.flowAnalysis.ifNullExpression_end();
+    flowAnalysis.ifNullExpression_end();
 
     // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
     //   UP(t0, t1)
     // - Then the inferred type is T.
     DartType originalLhsType = lhsResult.inferredType;
     DartType nonNullableLhsType = originalLhsType.toNonNull();
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(nonNullableLhsType, rhsResult.inferredType,
-            inferrer.libraryBuilder.library);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        nonNullableLhsType, rhsResult.inferredType, libraryBuilder.library);
     Expression replacement;
     if (left is ThisExpression) {
       replacement = left;
     } else {
       VariableDeclaration variable =
           createVariable(left, lhsResult.inferredType);
-      Expression equalsNull = inferrer.createEqualsNull(
+      Expression equalsNull = createEqualsNull(
           lhsResult.expression.fileOffset, createVariableGet(variable));
       VariableGet variableGet = createVariableGet(variable);
-      if (inferrer.libraryBuilder.isNonNullableByDefault &&
+      if (libraryBuilder.isNonNullableByDefault &&
           !identical(nonNullableLhsType, originalLhsType)) {
         variableGet.promotedType = nonNullableLhsType;
       }
@@ -1669,91 +1643,88 @@
 
   @override
   StatementInferenceResult visitIfStatement(IfStatement node) {
-    inferrer.flowAnalysis.ifStatement_conditionBegin();
+    flowAnalysis.ifStatement_conditionBegin();
     InterfaceType expectedType =
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+        coreTypes.boolRawType(libraryBuilder.nonNullable);
     ExpressionInferenceResult conditionResult = inferExpression(
-        node.condition, expectedType, !inferrer.isTopLevel,
+        node.condition, expectedType, !isTopLevel,
         isVoidAllowed: true);
-    Expression condition = inferrer
-        .ensureAssignableResult(expectedType, conditionResult)
-        .expression;
+    Expression condition =
+        ensureAssignableResult(expectedType, conditionResult).expression;
     node.condition = condition..parent = node;
-    inferrer.flowAnalysis.ifStatement_thenBegin(condition, node);
+    flowAnalysis.ifStatement_thenBegin(condition, node);
     StatementInferenceResult thenResult = inferStatement(node.then);
     if (thenResult.hasChanged) {
       node.then = thenResult.statement..parent = node;
     }
     if (node.otherwise != null) {
-      inferrer.flowAnalysis.ifStatement_elseBegin();
+      flowAnalysis.ifStatement_elseBegin();
       StatementInferenceResult otherwiseResult =
           inferStatement(node.otherwise!);
       if (otherwiseResult.hasChanged) {
         node.otherwise = otherwiseResult.statement..parent = node;
       }
     }
-    inferrer.flowAnalysis.ifStatement_end(node.otherwise != null);
+    flowAnalysis.ifStatement_end(node.otherwise != null);
     return const StatementInferenceResult();
   }
 
   ExpressionInferenceResult visitIntJudgment(
       IntJudgment node, DartType typeContext) {
-    if (inferrer.isDoubleContext(typeContext)) {
+    if (isDoubleContext(typeContext)) {
       double? doubleValue = node.asDouble();
       if (doubleValue != null) {
         Expression replacement = new DoubleLiteral(doubleValue)
           ..fileOffset = node.fileOffset;
-        DartType inferredType = inferrer.coreTypes
-            .doubleRawType(inferrer.libraryBuilder.nonNullable);
+        DartType inferredType =
+            coreTypes.doubleRawType(libraryBuilder.nonNullable);
         return new ExpressionInferenceResult(inferredType, replacement);
       }
     }
     Expression? error = checkWebIntLiteralsErrorIfUnexact(
-        inferrer, node.value, node.literal, node.fileOffset);
+        node.value, node.literal, node.fileOffset);
     if (error != null) {
       return new ExpressionInferenceResult(const DynamicType(), error);
     }
-    DartType inferredType =
-        inferrer.coreTypes.intRawType(inferrer.libraryBuilder.nonNullable);
+    DartType inferredType = coreTypes.intRawType(libraryBuilder.nonNullable);
     return new ExpressionInferenceResult(inferredType, node);
   }
 
   ExpressionInferenceResult visitShadowLargeIntLiteral(
       ShadowLargeIntLiteral node, DartType typeContext) {
-    if (inferrer.isDoubleContext(typeContext)) {
+    if (isDoubleContext(typeContext)) {
       double? doubleValue = node.asDouble();
       if (doubleValue != null) {
         Expression replacement = new DoubleLiteral(doubleValue)
           ..fileOffset = node.fileOffset;
-        DartType inferredType = inferrer.coreTypes
-            .doubleRawType(inferrer.libraryBuilder.nonNullable);
+        DartType inferredType =
+            coreTypes.doubleRawType(libraryBuilder.nonNullable);
         return new ExpressionInferenceResult(inferredType, replacement);
       }
     }
 
     int? intValue = node.asInt64();
     if (intValue == null) {
-      Expression replacement = inferrer.helper.buildProblem(
+      Expression replacement = helper.buildProblem(
           templateIntegerLiteralIsOutOfRange.withArguments(node.literal),
           node.fileOffset,
           node.literal.length);
       return new ExpressionInferenceResult(const DynamicType(), replacement);
     }
     Expression? error = checkWebIntLiteralsErrorIfUnexact(
-        inferrer, intValue, node.literal, node.fileOffset);
+        intValue, node.literal, node.fileOffset);
     if (error != null) {
       return new ExpressionInferenceResult(const DynamicType(), error);
     }
     Expression replacement = new IntLiteral(intValue);
-    DartType inferredType =
-        inferrer.coreTypes.intRawType(inferrer.libraryBuilder.nonNullable);
+    DartType inferredType = coreTypes.intRawType(libraryBuilder.nonNullable);
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
   InitializerInferenceResult visitShadowInvalidInitializer(
       ShadowInvalidInitializer node) {
     ExpressionInferenceResult initializerResult = inferExpression(
-        node.variable.initializer!, const UnknownType(), !inferrer.isTopLevel,
+        node.variable.initializer!, const UnknownType(), !isTopLevel,
         isVoidAllowed: false);
     node.variable.initializer = initializerResult.expression
       ..parent = node.variable;
@@ -1763,7 +1734,7 @@
   InitializerInferenceResult visitShadowInvalidFieldInitializer(
       ShadowInvalidFieldInitializer node) {
     ExpressionInferenceResult initializerResult = inferExpression(
-        node.value, node.field.type, !inferrer.isTopLevel,
+        node.value, node.field.type, !isTopLevel,
         isVoidAllowed: false);
     node.value = initializerResult.expression..parent = node;
     return const SuccessfulInitializerInferenceResult();
@@ -1773,14 +1744,13 @@
   ExpressionInferenceResult visitIsExpression(
       IsExpression node, DartType typeContext) {
     ExpressionInferenceResult operandResult = inferExpression(
-        node.operand, const UnknownType(), !inferrer.isTopLevel,
+        node.operand, const UnknownType(), !isTopLevel,
         isVoidAllowed: false);
     node.operand = operandResult.expression..parent = node;
-    inferrer.flowAnalysis
-        .isExpression_end(node, node.operand, /*isNot:*/ false, node.type);
+    flowAnalysis.isExpression_end(
+        node, node.operand, /*isNot:*/ false, node.type);
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable),
-        node);
+        coreTypes.boolRawType(libraryBuilder.nonNullable), node);
   }
 
   @override
@@ -1789,13 +1759,13 @@
         node.body is IfStatement ||
         node.body is TryStatement;
     if (isSimpleBody) {
-      inferrer.flowAnalysis.labeledStatement_begin(node);
+      flowAnalysis.labeledStatement_begin(node);
     }
 
     StatementInferenceResult bodyResult = inferStatement(node.body);
 
     if (isSimpleBody) {
-      inferrer.flowAnalysis.labeledStatement_end();
+      flowAnalysis.labeledStatement_end();
     }
 
     if (bodyResult.hasChanged) {
@@ -1806,24 +1776,24 @@
 
   DartType? getSpreadElementType(
       DartType spreadType, DartType spreadTypeBound, bool isNullAware) {
-    if (inferrer.coreTypes.isNull(spreadTypeBound)) {
-      if (inferrer.isNonNullableByDefault) {
+    if (coreTypes.isNull(spreadTypeBound)) {
+      if (isNonNullableByDefault) {
         return isNullAware ? const NeverType.nonNullable() : null;
       } else {
         return isNullAware ? const NullType() : null;
       }
     }
     if (spreadTypeBound is InterfaceType) {
-      List<DartType>? supertypeArguments = inferrer.typeSchemaEnvironment
-          .getTypeArgumentsAsInstanceOf(
-              spreadTypeBound, inferrer.coreTypes.iterableClass);
+      List<DartType>? supertypeArguments =
+          typeSchemaEnvironment.getTypeArgumentsAsInstanceOf(
+              spreadTypeBound, coreTypes.iterableClass);
       if (supertypeArguments == null) {
         return null;
       }
       return supertypeArguments.single;
     } else if (spreadType is DynamicType) {
       return const DynamicType();
-    } else if (inferrer.coreTypes.isBottom(spreadType)) {
+    } else if (coreTypes.isBottom(spreadType)) {
       return const NeverType.nonNullable();
     }
     return null;
@@ -1840,8 +1810,8 @@
       ExpressionInferenceResult spreadResult = inferExpression(
           element.expression,
           new InterfaceType(
-              inferrer.coreTypes.iterableClass,
-              inferrer.libraryBuilder.nullableIfTrue(element.isNullAware),
+              coreTypes.iterableClass,
+              libraryBuilder.nullableIfTrue(element.isNullAware),
               <DartType>[inferredTypeArgument]),
           inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
@@ -1853,98 +1823,95 @@
       DartType spreadType = spreadResult.inferredType;
       inferredSpreadTypes[element.expression] = spreadType;
       Expression replacement = element;
-      DartType spreadTypeBound = inferrer.resolveTypeParameter(spreadType);
+      DartType spreadTypeBound = resolveTypeParameter(spreadType);
       DartType? spreadElementType = getSpreadElementType(
           spreadType, spreadTypeBound, element.isNullAware);
       if (typeChecksNeeded) {
         if (spreadElementType == null) {
-          if (inferrer.coreTypes.isNull(spreadTypeBound) &&
-              !element.isNullAware) {
-            replacement = inferrer.helper.buildProblem(
+          if (coreTypes.isNull(spreadTypeBound) && !element.isNullAware) {
+            replacement = helper.buildProblem(
                 templateNonNullAwareSpreadIsNull.withArguments(
-                    spreadType, inferrer.isNonNullableByDefault),
+                    spreadType, isNonNullableByDefault),
                 element.expression.fileOffset,
                 1);
           } else {
-            if (inferrer.isNonNullableByDefault &&
+            if (isNonNullableByDefault &&
                 spreadType.isPotentiallyNullable &&
                 spreadType is! DynamicType &&
                 spreadType is! NullType &&
                 !element.isNullAware) {
               Expression receiver = element.expression;
-              replacement = inferrer.helper.buildProblem(
+              replacement = helper.buildProblem(
                   messageNullableSpreadError, receiver.fileOffset, 1,
-                  context: inferrer.getWhyNotPromotedContext(
-                      inferrer.flowAnalysis.whyNotPromoted(receiver)(),
+                  context: getWhyNotPromotedContext(
+                      flowAnalysis.whyNotPromoted(receiver)(),
                       element,
                       (type) => !type.isPotentiallyNullable));
             }
 
-            replacement = inferrer.helper.buildProblem(
+            replacement = helper.buildProblem(
                 templateSpreadTypeMismatch.withArguments(
-                    spreadType, inferrer.isNonNullableByDefault),
+                    spreadType, isNonNullableByDefault),
                 element.expression.fileOffset,
                 1);
             _copyNonPromotionReasonToReplacement(element, replacement);
           }
         } else if (spreadTypeBound is InterfaceType) {
-          if (!inferrer.isAssignable(inferredTypeArgument, spreadElementType)) {
-            if (inferrer.isNonNullableByDefault) {
-              IsSubtypeOf subtypeCheckResult = inferrer.typeSchemaEnvironment
-                  .performNullabilityAwareSubtypeCheck(
+          if (!isAssignable(inferredTypeArgument, spreadElementType)) {
+            if (isNonNullableByDefault) {
+              IsSubtypeOf subtypeCheckResult =
+                  typeSchemaEnvironment.performNullabilityAwareSubtypeCheck(
                       spreadElementType, inferredTypeArgument);
               if (subtypeCheckResult.isSubtypeWhenIgnoringNullabilities()) {
                 if (spreadElementType == subtypeCheckResult.subtype &&
                     inferredTypeArgument == subtypeCheckResult.supertype) {
-                  replacement = inferrer.helper.buildProblem(
+                  replacement = helper.buildProblem(
                       templateSpreadElementTypeMismatchNullability
-                          .withArguments(
-                              spreadElementType,
-                              inferredTypeArgument,
-                              inferrer.isNonNullableByDefault),
+                          .withArguments(spreadElementType,
+                              inferredTypeArgument, isNonNullableByDefault),
                       element.expression.fileOffset,
                       1);
                 } else {
-                  replacement = inferrer.helper.buildProblem(
+                  replacement = helper.buildProblem(
                       templateSpreadElementTypeMismatchPartNullability
                           .withArguments(
                               spreadElementType,
                               inferredTypeArgument,
                               subtypeCheckResult.subtype!,
                               subtypeCheckResult.supertype!,
-                              inferrer.isNonNullableByDefault),
+                              isNonNullableByDefault),
                       element.expression.fileOffset,
                       1);
                 }
               } else {
-                replacement = inferrer.helper.buildProblem(
+                replacement = helper.buildProblem(
                     templateSpreadElementTypeMismatch.withArguments(
                         spreadElementType,
                         inferredTypeArgument,
-                        inferrer.isNonNullableByDefault),
+                        isNonNullableByDefault),
                     element.expression.fileOffset,
                     1);
               }
             } else {
-              replacement = inferrer.helper.buildProblem(
+              replacement = helper.buildProblem(
                   templateSpreadElementTypeMismatch.withArguments(
                       spreadElementType,
                       inferredTypeArgument,
-                      inferrer.isNonNullableByDefault),
+                      isNonNullableByDefault),
                   element.expression.fileOffset,
                   1);
             }
           }
-          if (inferrer.isNonNullableByDefault &&
+          if (isNonNullableByDefault &&
               spreadType.isPotentiallyNullable &&
               spreadType is! DynamicType &&
               spreadType is! NullType &&
               !element.isNullAware) {
             Expression receiver = element.expression;
-            replacement = inferrer.helper.buildProblem(
+            replacement = helper.buildProblem(
                 messageNullableSpreadError, receiver.fileOffset, 1,
-                context: inferrer.getWhyNotPromotedContext(
-                    inferrer.flowAnalysis.whyNotPromoted(receiver)(),
+                context: getWhyNotPromotedContext(
+                    flowAnalysis.whyNotPromoted(receiver)(),
                     element,
                     (type) => !type.isPotentiallyNullable));
             _copyNonPromotionReasonToReplacement(element, replacement);
@@ -1955,16 +1922,15 @@
       element.elementType = spreadElementType ?? const DynamicType();
       return new ExpressionInferenceResult(element.elementType!, replacement);
     } else if (element is IfElement) {
-      inferrer.flowAnalysis.ifStatement_conditionBegin();
-      DartType boolType =
-          inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+      flowAnalysis.ifStatement_conditionBegin();
+      DartType boolType = coreTypes.boolRawType(libraryBuilder.nonNullable);
       ExpressionInferenceResult conditionResult = inferExpression(
           element.condition, boolType, typeChecksNeeded,
           isVoidAllowed: false);
       Expression condition =
-          inferrer.ensureAssignableResult(boolType, conditionResult).expression;
+          ensureAssignableResult(boolType, conditionResult).expression;
       element.condition = condition..parent = element;
-      inferrer.flowAnalysis.ifStatement_thenBegin(condition, element);
+      flowAnalysis.ifStatement_thenBegin(condition, element);
       ExpressionInferenceResult thenResult = inferElement(
           element.then,
           inferredTypeArgument,
@@ -1975,7 +1941,7 @@
       element.then = thenResult.expression..parent = element;
       ExpressionInferenceResult? otherwiseResult;
       if (element.otherwise != null) {
-        inferrer.flowAnalysis.ifStatement_elseBegin();
+        flowAnalysis.ifStatement_elseBegin();
         otherwiseResult = inferElement(
             element.otherwise!,
             inferredTypeArgument,
@@ -1985,14 +1951,14 @@
             typeChecksNeeded);
         element.otherwise = otherwiseResult.expression..parent = element;
       }
-      inferrer.flowAnalysis.ifStatement_end(element.otherwise != null);
+      flowAnalysis.ifStatement_end(element.otherwise != null);
       return new ExpressionInferenceResult(
           otherwiseResult == null
               ? thenResult.inferredType
-              : inferrer.typeSchemaEnvironment.getStandardUpperBound(
+              : typeSchemaEnvironment.getStandardUpperBound(
                   thenResult.inferredType,
                   otherwiseResult.inferredType,
-                  inferrer.libraryBuilder.library),
+                  libraryBuilder.library),
           element);
     } else if (element is ForElement) {
       // TODO(johnniwinther): Use _visitStatements instead.
@@ -2034,18 +2000,18 @@
         element.variables.addAll(variables);
         setParents(variables, element);
       }
-      inferrer.flowAnalysis.for_conditionBegin(element);
+      flowAnalysis.for_conditionBegin(element);
       if (element.condition != null) {
         ExpressionInferenceResult conditionResult = inferExpression(
             element.condition!,
-            inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable),
+            coreTypes.boolRawType(libraryBuilder.nonNullable),
             inferenceNeeded || typeChecksNeeded,
             isVoidAllowed: false);
         element.condition = conditionResult.expression..parent = element;
         inferredConditionTypes[element.condition!] =
             conditionResult.inferredType;
       }
-      inferrer.flowAnalysis.for_bodyBegin(null, element.condition);
+      flowAnalysis.for_bodyBegin(null, element.condition);
       ExpressionInferenceResult bodyResult = inferElement(
           element.body,
           inferredTypeArgument,
@@ -2054,7 +2020,7 @@
           inferenceNeeded,
           typeChecksNeeded);
       element.body = bodyResult.expression..parent = element;
-      inferrer.flowAnalysis.for_updaterBegin();
+      flowAnalysis.for_updaterBegin();
       for (int index = 0; index < element.updates.length; index++) {
         ExpressionInferenceResult updateResult = inferExpression(
             element.updates[index],
@@ -2063,7 +2029,7 @@
             isVoidAllowed: true);
         element.updates[index] = updateResult.expression..parent = element;
       }
-      inferrer.flowAnalysis.for_end();
+      flowAnalysis.for_end();
       return new ExpressionInferenceResult(bodyResult.inferredType, element);
     } else if (element is ForInElement) {
       ForInResult result;
@@ -2108,14 +2074,14 @@
       element.body = bodyResult.expression..parent = element;
       // This is matched by the call to [forEach_bodyBegin] in
       // [handleForInWithoutVariable] or [handleForInDeclaringVariable].
-      inferrer.flowAnalysis.forEach_end();
+      flowAnalysis.forEach_end();
       return new ExpressionInferenceResult(bodyResult.inferredType, element);
     } else {
       ExpressionInferenceResult result = inferExpression(
           element, inferredTypeArgument, inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
       if (inferredTypeArgument is! UnknownType) {
-        result = inferrer.ensureAssignableResult(inferredTypeArgument, result,
+        result = ensureAssignableResult(inferredTypeArgument, result,
             isVoidAllowed: inferredTypeArgument is VoidType);
       }
       return result;
@@ -2125,11 +2091,9 @@
   void _copyNonPromotionReasonToReplacement(
       TreeNode oldNode, TreeNode replacement) {
     if (!identical(oldNode, replacement) &&
-        inferrer.dataForTesting?.flowAnalysisResult != null) {
-      inferrer.dataForTesting!.flowAnalysisResult
-              .nonPromotionReasons[replacement] =
-          inferrer
-              .dataForTesting!.flowAnalysisResult.nonPromotionReasons[oldNode]!;
+        dataForTesting?.flowAnalysisResult != null) {
+      dataForTesting!.flowAnalysisResult.nonPromotionReasons[replacement] =
+          dataForTesting!.flowAnalysisResult.nonPromotionReasons[oldNode]!;
     }
   }
 
@@ -2142,9 +2106,9 @@
     if (item is SpreadElement) {
       DartType? spreadType = inferredSpreadTypes[item.expression];
       if (spreadType is DynamicType) {
-        Expression expression = inferrer.ensureAssignable(
-            inferrer.coreTypes.iterableRawType(
-                inferrer.libraryBuilder.nullableIfTrue(item.isNullAware)),
+        Expression expression = ensureAssignable(
+            coreTypes.iterableRawType(
+                libraryBuilder.nullableIfTrue(item.isNullAware)),
             spreadType,
             item.expression);
         item.expression = expression..parent = item;
@@ -2159,8 +2123,8 @@
     } else if (item is ForElement) {
       if (item.condition != null) {
         DartType conditionType = inferredConditionTypes[item.condition]!;
-        Expression condition = inferrer.ensureAssignable(
-            inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable),
+        Expression condition = ensureAssignable(
+            coreTypes.boolRawType(libraryBuilder.nonNullable),
             conditionType,
             item.condition!);
         item.condition = condition..parent = item;
@@ -2178,15 +2142,15 @@
   @override
   ExpressionInferenceResult visitListLiteral(
       ListLiteral node, DartType typeContext) {
-    Class listClass = inferrer.coreTypes.listClass;
-    InterfaceType listType = inferrer.coreTypes
-        .thisInterfaceType(listClass, inferrer.libraryBuilder.nonNullable);
+    Class listClass = coreTypes.listClass;
+    InterfaceType listType =
+        coreTypes.thisInterfaceType(listClass, libraryBuilder.nonNullable);
     List<DartType>? inferredTypes;
     DartType inferredTypeArgument;
     List<DartType>? formalTypes;
     List<DartType>? actualTypes;
     bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument;
-    bool typeChecksNeeded = !inferrer.isTopLevel;
+    bool typeChecksNeeded = !isTopLevel;
     Map<TreeNode, DartType>? inferredSpreadTypes;
     Map<Expression, DartType>? inferredConditionTypes;
     if (inferenceNeeded || typeChecksNeeded) {
@@ -2197,14 +2161,11 @@
     }
     TypeConstraintGatherer? gatherer;
     if (inferenceNeeded) {
-      gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
-          listType,
-          listClass.typeParameters,
-          typeContext,
-          inferrer.libraryBuilder.library,
+      gatherer = typeSchemaEnvironment.setupGenericTypeInference(listType,
+          listClass.typeParameters, typeContext, libraryBuilder.library,
           isConst: node.isConst);
-      inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
-          listClass.typeParameters, null, inferrer.libraryBuilder.library);
+      inferredTypes = typeSchemaEnvironment.partialInfer(
+          gatherer, listClass.typeParameters, null, libraryBuilder.library);
       inferredTypeArgument = inferredTypes[0];
     } else {
       inferredTypeArgument = node.typeArgument;
@@ -2227,18 +2188,15 @@
     }
     if (inferenceNeeded) {
       gatherer!.constrainArguments(formalTypes!, actualTypes!);
-      inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
-          gatherer,
-          listClass.typeParameters,
-          inferredTypes!,
-          inferrer.libraryBuilder.library);
-      if (inferrer.dataForTesting != null) {
-        inferrer.dataForTesting!.typeInferenceResult
-            .inferredTypeArguments[node] = inferredTypes;
+      inferredTypes = typeSchemaEnvironment.upwardsInfer(gatherer,
+          listClass.typeParameters, inferredTypes!, libraryBuilder.library);
+      if (dataForTesting != null) {
+        dataForTesting!.typeInferenceResult.inferredTypeArguments[node] =
+            inferredTypes;
       }
       inferredTypeArgument = inferredTypes[0];
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
+      instrumentation?.record(
+          uriForInstrumentation,
           node.fileOffset,
           'typeArgs',
           new InstrumentationValueForTypeArgs([inferredTypeArgument]));
@@ -2251,13 +2209,12 @@
       }
     }
     DartType inferredType = new InterfaceType(
-        listClass, inferrer.libraryBuilder.nonNullable, [inferredTypeArgument]);
-    if (!inferrer.isTopLevel) {
-      SourceLibraryBuilder library = inferrer.libraryBuilder;
+        listClass, libraryBuilder.nonNullable, [inferredTypeArgument]);
+    if (!isTopLevel) {
+      SourceLibraryBuilder library = libraryBuilder;
       if (inferenceNeeded) {
         if (!library.libraryFeatures.genericMetadata.isEnabled) {
-          inferrer.checkGenericFunctionTypeArgument(
-              node.typeArgument, node.fileOffset);
+          checkGenericFunctionTypeArgument(node.typeArgument, node.fileOffset);
         }
       }
     }
@@ -2268,24 +2225,20 @@
   @override
   ExpressionInferenceResult visitLogicalExpression(
       LogicalExpression node, DartType typeContext) {
-    InterfaceType boolType =
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
-    inferrer.flowAnalysis.logicalBinaryOp_begin();
-    ExpressionInferenceResult leftResult = inferExpression(
-        node.left, boolType, !inferrer.isTopLevel,
-        isVoidAllowed: false);
-    Expression left =
-        inferrer.ensureAssignableResult(boolType, leftResult).expression;
+    InterfaceType boolType = coreTypes.boolRawType(libraryBuilder.nonNullable);
+    flowAnalysis.logicalBinaryOp_begin();
+    ExpressionInferenceResult leftResult =
+        inferExpression(node.left, boolType, !isTopLevel, isVoidAllowed: false);
+    Expression left = ensureAssignableResult(boolType, leftResult).expression;
     node.left = left..parent = node;
-    inferrer.flowAnalysis.logicalBinaryOp_rightBegin(node.left, node,
+    flowAnalysis.logicalBinaryOp_rightBegin(node.left, node,
         isAnd: node.operatorEnum == LogicalExpressionOperator.AND);
     ExpressionInferenceResult rightResult = inferExpression(
-        node.right, boolType, !inferrer.isTopLevel,
+        node.right, boolType, !isTopLevel,
         isVoidAllowed: false);
-    Expression right =
-        inferrer.ensureAssignableResult(boolType, rightResult).expression;
+    Expression right = ensureAssignableResult(boolType, rightResult).expression;
     node.right = right..parent = node;
-    inferrer.flowAnalysis.logicalBinaryOp_end(node, node.right,
+    flowAnalysis.logicalBinaryOp_end(node, node.right,
         isAnd: node.operatorEnum == LogicalExpressionOperator.AND);
     return new ExpressionInferenceResult(boolType, node);
   }
@@ -2296,25 +2249,25 @@
   // is a function type, the original values in output are preserved.
   void storeSpreadMapEntryElementTypes(DartType spreadMapEntryType,
       bool isNullAware, List<DartType?> output, int offset) {
-    DartType typeBound = inferrer.resolveTypeParameter(spreadMapEntryType);
-    if (inferrer.coreTypes.isNull(typeBound)) {
+    DartType typeBound = resolveTypeParameter(spreadMapEntryType);
+    if (coreTypes.isNull(typeBound)) {
       if (isNullAware) {
-        if (inferrer.isNonNullableByDefault) {
+        if (isNonNullableByDefault) {
           output[offset] = output[offset + 1] = const NeverType.nonNullable();
         } else {
           output[offset] = output[offset + 1] = const NullType();
         }
       }
     } else if (typeBound is InterfaceType) {
-      List<DartType>? supertypeArguments = inferrer.typeSchemaEnvironment
-          .getTypeArgumentsAsInstanceOf(typeBound, inferrer.coreTypes.mapClass);
+      List<DartType>? supertypeArguments = typeSchemaEnvironment
+          .getTypeArgumentsAsInstanceOf(typeBound, coreTypes.mapClass);
       if (supertypeArguments != null) {
         output[offset] = supertypeArguments[0];
         output[offset + 1] = supertypeArguments[1];
       }
     } else if (spreadMapEntryType is DynamicType) {
       output[offset] = output[offset + 1] = const DynamicType();
-    } else if (inferrer.coreTypes.isBottom(spreadMapEntryType)) {
+    } else if (coreTypes.isBottom(spreadMapEntryType)) {
       output[offset] = output[offset + 1] = const NeverType.nonNullable();
     }
   }
@@ -2355,34 +2308,33 @@
           spreadType, entry.isNullAware, actualTypes, length);
       DartType? actualKeyType = actualTypes[length];
       DartType? actualValueType = actualTypes[length + 1];
-      DartType spreadTypeBound = inferrer.resolveTypeParameter(spreadType);
+      DartType spreadTypeBound = resolveTypeParameter(spreadType);
       DartType? actualElementType =
           getSpreadElementType(spreadType, spreadTypeBound, entry.isNullAware);
 
       MapLiteralEntry replacement = entry;
       if (typeChecksNeeded) {
         if (actualKeyType == noInferredType) {
-          if (inferrer.coreTypes.isNull(spreadTypeBound) &&
-              !entry.isNullAware) {
+          if (coreTypes.isNull(spreadTypeBound) && !entry.isNullAware) {
             replacement = new MapLiteralEntry(
-                inferrer.helper.buildProblem(
+                helper.buildProblem(
                     templateNonNullAwareSpreadIsNull.withArguments(
-                        spreadType, inferrer.isNonNullableByDefault),
+                        spreadType, isNonNullableByDefault),
                     entry.expression.fileOffset,
                     1),
                 new NullLiteral())
               ..fileOffset = entry.fileOffset;
           } else if (actualElementType != null) {
-            if (inferrer.isNonNullableByDefault &&
+            if (isNonNullableByDefault &&
                 spreadType.isPotentiallyNullable &&
                 spreadType is! DynamicType &&
                 spreadType is! NullType &&
                 !entry.isNullAware) {
               Expression receiver = entry.expression;
-              Expression problem = inferrer.helper.buildProblem(
+              Expression problem = helper.buildProblem(
                   messageNullableSpreadError, receiver.fileOffset, 1,
-                  context: inferrer.getWhyNotPromotedContext(
-                      inferrer.flowAnalysis.whyNotPromoted(receiver)(),
+                  context: getWhyNotPromotedContext(
+                      flowAnalysis.whyNotPromoted(receiver)(),
                       entry,
                       (type) => !type.isPotentiallyNullable));
               _copyNonPromotionReasonToReplacement(entry, problem);
@@ -2395,13 +2347,13 @@
             offsets.iterableSpreadType = spreadType;
           } else {
             Expression receiver = entry.expression;
-            Expression problem = inferrer.helper.buildProblem(
+            Expression problem = helper.buildProblem(
                 templateSpreadMapEntryTypeMismatch.withArguments(
-                    spreadType, inferrer.isNonNullableByDefault),
+                    spreadType, isNonNullableByDefault),
                 receiver.fileOffset,
                 1,
-                context: inferrer.getWhyNotPromotedContext(
-                    inferrer.flowAnalysis.whyNotPromoted(receiver)(),
+                context: getWhyNotPromotedContext(
+                    flowAnalysis.whyNotPromoted(receiver)(),
                     entry,
                     (type) => !type.isPotentiallyNullable));
             _copyNonPromotionReasonToReplacement(entry, problem);
@@ -2411,22 +2363,22 @@
         } else if (spreadTypeBound is InterfaceType) {
           Expression? keyError;
           Expression? valueError;
-          if (!inferrer.isAssignable(inferredKeyType, actualKeyType)) {
-            if (inferrer.isNonNullableByDefault) {
-              IsSubtypeOf subtypeCheckResult = inferrer.typeSchemaEnvironment
-                  .performNullabilityAwareSubtypeCheck(
+          if (!isAssignable(inferredKeyType, actualKeyType)) {
+            if (isNonNullableByDefault) {
+              IsSubtypeOf subtypeCheckResult =
+                  typeSchemaEnvironment.performNullabilityAwareSubtypeCheck(
                       actualKeyType, inferredKeyType);
               if (subtypeCheckResult.isSubtypeWhenIgnoringNullabilities()) {
                 if (actualKeyType == subtypeCheckResult.subtype &&
                     inferredKeyType == subtypeCheckResult.supertype) {
-                  keyError = inferrer.helper.buildProblem(
+                  keyError = helper.buildProblem(
                       templateSpreadMapEntryElementKeyTypeMismatchNullability
                           .withArguments(actualKeyType, inferredKeyType,
-                              inferrer.isNonNullableByDefault),
+                              isNonNullableByDefault),
                       entry.expression.fileOffset,
                       1);
                 } else {
-                  keyError = inferrer.helper.buildProblem(
+                  keyError = helper.buildProblem(
                       // ignore: lines_longer_than_80_chars
                       templateSpreadMapEntryElementKeyTypeMismatchPartNullability
                           .withArguments(
@@ -2434,45 +2386,41 @@
                               inferredKeyType,
                               subtypeCheckResult.subtype!,
                               subtypeCheckResult.supertype!,
-                              inferrer.isNonNullableByDefault),
+                              isNonNullableByDefault),
                       entry.expression.fileOffset,
                       1);
                 }
               } else {
-                keyError = inferrer.helper.buildProblem(
+                keyError = helper.buildProblem(
                     templateSpreadMapEntryElementKeyTypeMismatch.withArguments(
-                        actualKeyType,
-                        inferredKeyType,
-                        inferrer.isNonNullableByDefault),
+                        actualKeyType, inferredKeyType, isNonNullableByDefault),
                     entry.expression.fileOffset,
                     1);
               }
             } else {
-              keyError = inferrer.helper.buildProblem(
+              keyError = helper.buildProblem(
                   templateSpreadMapEntryElementKeyTypeMismatch.withArguments(
-                      actualKeyType,
-                      inferredKeyType,
-                      inferrer.isNonNullableByDefault),
+                      actualKeyType, inferredKeyType, isNonNullableByDefault),
                   entry.expression.fileOffset,
                   1);
             }
           }
-          if (!inferrer.isAssignable(inferredValueType, actualValueType)) {
-            if (inferrer.isNonNullableByDefault) {
-              IsSubtypeOf subtypeCheckResult = inferrer.typeSchemaEnvironment
-                  .performNullabilityAwareSubtypeCheck(
+          if (!isAssignable(inferredValueType, actualValueType)) {
+            if (isNonNullableByDefault) {
+              IsSubtypeOf subtypeCheckResult =
+                  typeSchemaEnvironment.performNullabilityAwareSubtypeCheck(
                       actualValueType, inferredValueType);
               if (subtypeCheckResult.isSubtypeWhenIgnoringNullabilities()) {
                 if (actualValueType == subtypeCheckResult.subtype &&
                     inferredValueType == subtypeCheckResult.supertype) {
-                  valueError = inferrer.helper.buildProblem(
+                  valueError = helper.buildProblem(
                       templateSpreadMapEntryElementValueTypeMismatchNullability
                           .withArguments(actualValueType, inferredValueType,
-                              inferrer.isNonNullableByDefault),
+                              isNonNullableByDefault),
                       entry.expression.fileOffset,
                       1);
                 } else {
-                  valueError = inferrer.helper.buildProblem(
+                  valueError = helper.buildProblem(
                       // ignore: lines_longer_than_80_chars
                       templateSpreadMapEntryElementValueTypeMismatchPartNullability
                           .withArguments(
@@ -2480,38 +2428,38 @@
                               inferredValueType,
                               subtypeCheckResult.subtype!,
                               subtypeCheckResult.supertype!,
-                              inferrer.isNonNullableByDefault),
+                              isNonNullableByDefault),
                       entry.expression.fileOffset,
                       1);
                 }
               } else {
-                valueError = inferrer.helper.buildProblem(
+                valueError = helper.buildProblem(
                     templateSpreadMapEntryElementValueTypeMismatch
                         .withArguments(actualValueType, inferredValueType,
-                            inferrer.isNonNullableByDefault),
+                            isNonNullableByDefault),
                     entry.expression.fileOffset,
                     1);
               }
             } else {
-              valueError = inferrer.helper.buildProblem(
+              valueError = helper.buildProblem(
                   templateSpreadMapEntryElementValueTypeMismatch.withArguments(
                       actualValueType,
                       inferredValueType,
-                      inferrer.isNonNullableByDefault),
+                      isNonNullableByDefault),
                   entry.expression.fileOffset,
                   1);
             }
           }
-          if (inferrer.isNonNullableByDefault &&
+          if (isNonNullableByDefault &&
               spreadType.isPotentiallyNullable &&
               spreadType is! DynamicType &&
               spreadType is! NullType &&
               !entry.isNullAware) {
             Expression receiver = entry.expression;
-            keyError = inferrer.helper.buildProblem(
+            keyError = helper.buildProblem(
                 messageNullableSpreadError, receiver.fileOffset, 1,
-                context: inferrer.getWhyNotPromotedContext(
-                    inferrer.flowAnalysis.whyNotPromoted(receiver)(),
+                context: getWhyNotPromotedContext(
+                    flowAnalysis.whyNotPromoted(receiver)(),
                     entry,
                     (type) => !type.isPotentiallyNullable));
             _copyNonPromotionReasonToReplacement(entry, keyError);
@@ -2534,21 +2482,20 @@
       // recovery.
       actualTypesForSet.add(actualElementType ?? const DynamicType());
 
-      mapEntryClass ??=
-          inferrer.coreTypes.index.getClass('dart:core', 'MapEntry');
+      mapEntryClass ??= coreTypes.index.getClass('dart:core', 'MapEntry');
       // TODO(cstefantsova):  Handle the case of an ambiguous Set.
       entry.entryType = new InterfaceType(
           mapEntryClass!,
-          inferrer.libraryBuilder.nonNullable,
+          libraryBuilder.nonNullable,
           <DartType>[actualKeyType, actualValueType]);
 
-      bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
+      bool isMap = typeSchemaEnvironment.isSubtypeOf(
           spreadType,
-          inferrer.coreTypes.mapRawType(inferrer.libraryBuilder.nullable),
+          coreTypes.mapRawType(libraryBuilder.nullable),
           SubtypeCheckMode.withNullabilities);
-      bool isIterable = inferrer.typeSchemaEnvironment.isSubtypeOf(
+      bool isIterable = typeSchemaEnvironment.isSubtypeOf(
           spreadType,
-          inferrer.coreTypes.iterableRawType(inferrer.libraryBuilder.nullable),
+          coreTypes.iterableRawType(libraryBuilder.nullable),
           SubtypeCheckMode.withNullabilities);
       if (isMap && !isIterable) {
         offsets.mapSpreadOffset = entry.fileOffset;
@@ -2559,16 +2506,15 @@
 
       return replacement;
     } else if (entry is IfMapEntry) {
-      inferrer.flowAnalysis.ifStatement_conditionBegin();
-      DartType boolType =
-          inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+      flowAnalysis.ifStatement_conditionBegin();
+      DartType boolType = coreTypes.boolRawType(libraryBuilder.nonNullable);
       ExpressionInferenceResult conditionResult = inferExpression(
           entry.condition, boolType, typeChecksNeeded,
           isVoidAllowed: false);
       Expression condition =
-          inferrer.ensureAssignableResult(boolType, conditionResult).expression;
+          ensureAssignableResult(boolType, conditionResult).expression;
       entry.condition = condition..parent = entry;
-      inferrer.flowAnalysis.ifStatement_thenBegin(condition, entry);
+      flowAnalysis.ifStatement_thenBegin(condition, entry);
       // Note that this recursive invocation of inferMapEntry will add two types
       // to actualTypes; they are the actual types of the current invocation if
       // the 'else' branch is empty.
@@ -2587,7 +2533,7 @@
           offsets);
       entry.then = then..parent = entry;
       if (entry.otherwise != null) {
-        inferrer.flowAnalysis.ifStatement_elseBegin();
+        flowAnalysis.ifStatement_elseBegin();
         // We need to modify the actual types added in the recursive call to
         // inferMapEntry.
         DartType? actualValueType = actualTypes.removeLast();
@@ -2607,21 +2553,17 @@
             typeChecksNeeded,
             offsets);
         int length = actualTypes.length;
-        actualTypes[length - 2] = inferrer.typeSchemaEnvironment
-            .getStandardUpperBound(actualKeyType, actualTypes[length - 2],
-                inferrer.libraryBuilder.library);
-        actualTypes[length - 1] = inferrer.typeSchemaEnvironment
-            .getStandardUpperBound(actualValueType, actualTypes[length - 1],
-                inferrer.libraryBuilder.library);
+        actualTypes[length - 2] = typeSchemaEnvironment.getStandardUpperBound(
+            actualKeyType, actualTypes[length - 2], libraryBuilder.library);
+        actualTypes[length - 1] = typeSchemaEnvironment.getStandardUpperBound(
+            actualValueType, actualTypes[length - 1], libraryBuilder.library);
         int lengthForSet = actualTypesForSet.length;
-        actualTypesForSet[lengthForSet - 1] = inferrer.typeSchemaEnvironment
-            .getStandardUpperBound(
-                actualTypeForSet,
-                actualTypesForSet[lengthForSet - 1],
-                inferrer.libraryBuilder.library);
+        actualTypesForSet[lengthForSet - 1] =
+            typeSchemaEnvironment.getStandardUpperBound(actualTypeForSet,
+                actualTypesForSet[lengthForSet - 1], libraryBuilder.library);
         entry.otherwise = otherwise..parent = entry;
       }
-      inferrer.flowAnalysis.ifStatement_end(entry.otherwise != null);
+      flowAnalysis.ifStatement_end(entry.otherwise != null);
       return entry;
     } else if (entry is ForMapEntry) {
       // TODO(johnniwinther): Use _visitStatements instead.
@@ -2662,18 +2604,18 @@
         entry.variables.addAll(variables);
         setParents(variables, entry);
       }
-      inferrer.flowAnalysis.for_conditionBegin(entry);
+      flowAnalysis.for_conditionBegin(entry);
       if (entry.condition != null) {
         ExpressionInferenceResult conditionResult = inferExpression(
             entry.condition!,
-            inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable),
+            coreTypes.boolRawType(libraryBuilder.nonNullable),
             inferenceNeeded || typeChecksNeeded,
             isVoidAllowed: false);
         entry.condition = conditionResult.expression..parent = entry;
         // TODO(johnniwinther): Ensure assignability of condition?
         inferredConditionTypes[entry.condition!] = conditionResult.inferredType;
       }
-      inferrer.flowAnalysis.for_bodyBegin(null, entry.condition);
+      flowAnalysis.for_bodyBegin(null, entry.condition);
       // Actual types are added by the recursive call.
       MapLiteralEntry body = inferMapEntry(
           entry.body,
@@ -2689,7 +2631,7 @@
           typeChecksNeeded,
           offsets);
       entry.body = body..parent = entry;
-      inferrer.flowAnalysis.for_updaterBegin();
+      flowAnalysis.for_updaterBegin();
       for (int index = 0; index < entry.updates.length; index++) {
         ExpressionInferenceResult updateResult = inferExpression(
             entry.updates[index],
@@ -2698,7 +2640,7 @@
             isVoidAllowed: true);
         entry.updates[index] = updateResult.expression..parent = entry;
       }
-      inferrer.flowAnalysis.for_end();
+      flowAnalysis.for_end();
       return entry;
     } else if (entry is ForInMapEntry) {
       ForInResult result;
@@ -2744,22 +2686,20 @@
       entry.body = body..parent = entry;
       // This is matched by the call to [forEach_bodyBegin] in
       // [handleForInWithoutVariable] or [handleForInDeclaringVariable].
-      inferrer.flowAnalysis.forEach_end();
+      flowAnalysis.forEach_end();
       return entry;
     } else {
       ExpressionInferenceResult keyResult = inferExpression(
           entry.key, inferredKeyType, true,
           isVoidAllowed: true);
-      Expression key = inferrer
-          .ensureAssignableResult(inferredKeyType, keyResult,
+      Expression key = ensureAssignableResult(inferredKeyType, keyResult,
               isVoidAllowed: inferredKeyType is VoidType)
           .expression;
       entry.key = key..parent = entry;
       ExpressionInferenceResult valueResult = inferExpression(
           entry.value, inferredValueType, true,
           isVoidAllowed: true);
-      Expression value = inferrer
-          .ensureAssignableResult(inferredValueType, valueResult,
+      Expression value = ensureAssignableResult(inferredValueType, valueResult,
               isVoidAllowed: inferredValueType is VoidType)
           .expression;
       entry.value = value..parent = entry;
@@ -2783,9 +2723,9 @@
     MapLiteralEntry replacement = entry;
     if (offsets.iterableSpreadOffset != null) {
       replacement = new MapLiteralEntry(
-          inferrer.helper.buildProblem(
+          helper.buildProblem(
               templateSpreadMapEntryTypeMismatch.withArguments(
-                  offsets.iterableSpreadType!, inferrer.isNonNullableByDefault),
+                  offsets.iterableSpreadType!, isNonNullableByDefault),
               offsets.iterableSpreadOffset!,
               1),
           new NullLiteral())
@@ -2794,9 +2734,9 @@
     if (entry is SpreadMapEntry) {
       DartType? spreadType = inferredSpreadTypes[entry.expression];
       if (spreadType is DynamicType) {
-        Expression expression = inferrer.ensureAssignable(
-            inferrer.coreTypes.mapRawType(
-                inferrer.libraryBuilder.nullableIfTrue(entry.isNullAware)),
+        Expression expression = ensureAssignable(
+            coreTypes
+                .mapRawType(libraryBuilder.nullableIfTrue(entry.isNullAware)),
             spreadType,
             entry.expression);
         entry.expression = expression..parent = entry;
@@ -2813,8 +2753,8 @@
     } else if (entry is ForMapEntry) {
       if (entry.condition != null) {
         DartType conditionType = inferredConditionTypes[entry.condition]!;
-        Expression condition = inferrer.ensureAssignable(
-            inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable),
+        Expression condition = ensureAssignable(
+            coreTypes.boolRawType(libraryBuilder.nonNullable),
             conditionType,
             entry.condition!);
         entry.condition = condition..parent = entry;
@@ -2835,9 +2775,9 @@
   @override
   ExpressionInferenceResult visitMapLiteral(
       MapLiteral node, DartType typeContext) {
-    Class mapClass = inferrer.coreTypes.mapClass;
-    InterfaceType mapType = inferrer.coreTypes
-        .thisInterfaceType(mapClass, inferrer.libraryBuilder.nonNullable);
+    Class mapClass = coreTypes.mapClass;
+    InterfaceType mapType =
+        coreTypes.thisInterfaceType(mapClass, libraryBuilder.nonNullable);
     List<DartType>? inferredTypes;
     DartType inferredKeyType;
     DartType inferredValueType;
@@ -2849,17 +2789,16 @@
     bool inferenceNeeded = node.keyType is ImplicitTypeArgument;
     bool typeContextIsMap = node.keyType is! ImplicitTypeArgument;
     bool typeContextIsIterable = false;
-    DartType? unfuturedTypeContext =
-        inferrer.typeSchemaEnvironment.flatten(typeContext);
-    if (!inferrer.isTopLevel && inferenceNeeded) {
+    DartType? unfuturedTypeContext = typeSchemaEnvironment.flatten(typeContext);
+    if (!isTopLevel && inferenceNeeded) {
       // Ambiguous set/map literal
       if (unfuturedTypeContext is InterfaceType) {
         typeContextIsMap = typeContextIsMap ||
-            inferrer.classHierarchy.isSubtypeOf(
-                unfuturedTypeContext.classNode, inferrer.coreTypes.mapClass);
+            classHierarchy.isSubtypeOf(
+                unfuturedTypeContext.classNode, coreTypes.mapClass);
         typeContextIsIterable = typeContextIsIterable ||
-            inferrer.classHierarchy.isSubtypeOf(unfuturedTypeContext.classNode,
-                inferrer.coreTypes.iterableClass);
+            classHierarchy.isSubtypeOf(
+                unfuturedTypeContext.classNode, coreTypes.iterableClass);
         if (node.entries.isEmpty &&
             typeContextIsIterable &&
             !typeContextIsMap) {
@@ -2871,7 +2810,7 @@
         }
       }
     }
-    bool typeChecksNeeded = !inferrer.isTopLevel;
+    bool typeChecksNeeded = !isTopLevel;
     Map<TreeNode, DartType>? inferredSpreadTypes;
     Map<Expression, DartType>? inferredConditionTypes;
     if (inferenceNeeded || typeChecksNeeded) {
@@ -2883,14 +2822,11 @@
     }
     TypeConstraintGatherer? gatherer;
     if (inferenceNeeded) {
-      gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
-          mapType,
-          mapClass.typeParameters,
-          typeContext,
-          inferrer.libraryBuilder.library,
+      gatherer = typeSchemaEnvironment.setupGenericTypeInference(
+          mapType, mapClass.typeParameters, typeContext, libraryBuilder.library,
           isConst: node.isConst);
-      inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
-          mapClass.typeParameters, null, inferrer.libraryBuilder.library);
+      inferredTypes = typeSchemaEnvironment.partialInfer(
+          gatherer, mapClass.typeParameters, null, libraryBuilder.library);
       inferredKeyType = inferredTypes[0];
       inferredValueType = inferredTypes[1];
     } else {
@@ -2904,15 +2840,15 @@
     if (inferenceNeeded || typeChecksNeeded) {
       DartType spreadTypeContext = const UnknownType();
       if (typeContextIsIterable && !typeContextIsMap) {
-        spreadTypeContext = inferrer.typeSchemaEnvironment.getTypeAsInstanceOf(
+        spreadTypeContext = typeSchemaEnvironment.getTypeAsInstanceOf(
             unfuturedTypeContext as InterfaceType,
-            inferrer.coreTypes.iterableClass,
-            inferrer.libraryBuilder.library,
-            inferrer.coreTypes)!;
+            coreTypes.iterableClass,
+            libraryBuilder.library,
+            coreTypes)!;
       } else if (!typeContextIsIterable && typeContextIsMap) {
         spreadTypeContext = new InterfaceType(
-            inferrer.coreTypes.mapClass,
-            inferrer.libraryBuilder.nonNullable,
+            coreTypes.mapClass,
+            libraryBuilder.nonNullable,
             <DartType>[inferredKeyType, inferredValueType]);
       }
       for (int index = 0; index < node.entries.length; ++index) {
@@ -2945,38 +2881,38 @@
       if (canBeSet && !canBeMap) {
         List<Expression> setElements = <Expression>[];
         List<DartType> formalTypesForSet = <DartType>[];
-        InterfaceType setType = inferrer.coreTypes.thisInterfaceType(
-            inferrer.coreTypes.setClass, inferrer.libraryBuilder.nonNullable);
+        InterfaceType setType = coreTypes.thisInterfaceType(
+            coreTypes.setClass, libraryBuilder.nonNullable);
         for (int i = 0; i < node.entries.length; ++i) {
-          setElements.add(convertToElement(
-              node.entries[i],
-              inferrer.isTopLevel ? null : inferrer.helper,
-              inferrer.assignedVariables.reassignInfo));
+          setElements.add(convertToElement(node.entries[i],
+              isTopLevel ? null : helper, assignedVariables.reassignInfo));
           formalTypesForSet.add(setType.typeArguments[0]);
         }
 
         // Note: we don't use the previously created gatherer because it was set
         // up presuming that the literal would be a map; we now know that it
         // needs to be a set.
-        TypeConstraintGatherer gatherer = inferrer.typeSchemaEnvironment
-            .setupGenericTypeInference(
+        TypeConstraintGatherer gatherer =
+            typeSchemaEnvironment.setupGenericTypeInference(
                 setType,
-                inferrer.coreTypes.setClass.typeParameters,
+                coreTypes.setClass.typeParameters,
                 typeContext,
-                inferrer.libraryBuilder.library,
+                libraryBuilder.library,
                 isConst: node.isConst);
-        List<DartType> inferredTypesForSet = inferrer.typeSchemaEnvironment
-            .partialInfer(gatherer, inferrer.coreTypes.setClass.typeParameters,
-                null, inferrer.libraryBuilder.library);
-        gatherer.constrainArguments(formalTypesForSet, actualTypesForSet!);
-        inferredTypesForSet = inferrer.typeSchemaEnvironment.upwardsInfer(
+        List<DartType> inferredTypesForSet = typeSchemaEnvironment.partialInfer(
             gatherer,
-            inferrer.coreTypes.setClass.typeParameters,
+            coreTypes.setClass.typeParameters,
+            null,
+            libraryBuilder.library);
+        gatherer.constrainArguments(formalTypesForSet, actualTypesForSet!);
+        inferredTypesForSet = typeSchemaEnvironment.upwardsInfer(
+            gatherer,
+            coreTypes.setClass.typeParameters,
             inferredTypesForSet,
-            inferrer.libraryBuilder.library);
+            libraryBuilder.library);
         DartType inferredTypeArgument = inferredTypesForSet[0];
-        inferrer.instrumentation?.record(
-            inferrer.uriForInstrumentation,
+        instrumentation?.record(
+            uriForInstrumentation,
             node.fileOffset,
             'typeArgs',
             new InstrumentationValueForTypeArgs([inferredTypeArgument]));
@@ -2995,44 +2931,39 @@
           }
         }
 
-        DartType inferredType = new InterfaceType(inferrer.coreTypes.setClass,
-            inferrer.libraryBuilder.nonNullable, inferredTypesForSet);
+        DartType inferredType = new InterfaceType(coreTypes.setClass,
+            libraryBuilder.nonNullable, inferredTypesForSet);
         return new ExpressionInferenceResult(inferredType, setLiteral);
       }
       if (canBeSet && canBeMap && node.entries.isNotEmpty) {
         Expression replacement = node;
-        if (!inferrer.isTopLevel) {
-          replacement = inferrer.helper.buildProblem(
+        if (!isTopLevel) {
+          replacement = helper.buildProblem(
               messageCantDisambiguateNotEnoughInformation, node.fileOffset, 1);
         }
         return new ExpressionInferenceResult(
-            NeverType.fromNullability(inferrer.libraryBuilder.nonNullable),
-            replacement);
+            NeverType.fromNullability(libraryBuilder.nonNullable), replacement);
       }
       if (!canBeSet && !canBeMap) {
         Expression replacement = node;
-        if (!inferrer.isTopLevel) {
-          replacement = inferrer.helper.buildProblem(
+        if (!isTopLevel) {
+          replacement = helper.buildProblem(
               messageCantDisambiguateAmbiguousInformation, node.fileOffset, 1);
         }
         return new ExpressionInferenceResult(
-            NeverType.fromNullability(inferrer.libraryBuilder.nonNullable),
-            replacement);
+            NeverType.fromNullability(libraryBuilder.nonNullable), replacement);
       }
       gatherer!.constrainArguments(formalTypes!, actualTypes!);
-      inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
-          gatherer,
-          mapClass.typeParameters,
-          inferredTypes!,
-          inferrer.libraryBuilder.library);
-      if (inferrer.dataForTesting != null) {
-        inferrer.dataForTesting!.typeInferenceResult
-            .inferredTypeArguments[node] = inferredTypes;
+      inferredTypes = typeSchemaEnvironment.upwardsInfer(gatherer,
+          mapClass.typeParameters, inferredTypes!, libraryBuilder.library);
+      if (dataForTesting != null) {
+        dataForTesting!.typeInferenceResult.inferredTypeArguments[node] =
+            inferredTypes;
       }
       inferredKeyType = inferredTypes[0];
       inferredValueType = inferredTypes[1];
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
+      instrumentation?.record(
+          uriForInstrumentation,
           node.fileOffset,
           'typeArgs',
           new InstrumentationValueForTypeArgs(
@@ -3052,20 +2983,16 @@
         node.entries[index] = entry..parent = node;
       }
     }
-    DartType inferredType = new InterfaceType(
-        mapClass,
-        inferrer.libraryBuilder.nonNullable,
-        [inferredKeyType, inferredValueType]);
-    if (!inferrer.isTopLevel) {
-      SourceLibraryBuilder library = inferrer.libraryBuilder;
+    DartType inferredType = new InterfaceType(mapClass,
+        libraryBuilder.nonNullable, [inferredKeyType, inferredValueType]);
+    if (!isTopLevel) {
+      SourceLibraryBuilder library = libraryBuilder;
       // Either both [_declaredKeyType] and [_declaredValueType] are omitted or
       // none of them, so we may just check one.
       if (inferenceNeeded) {
         if (!library.libraryFeatures.genericMetadata.isEnabled) {
-          inferrer.checkGenericFunctionTypeArgument(
-              node.keyType, node.fileOffset);
-          inferrer.checkGenericFunctionTypeArgument(
-              node.valueType, node.fileOffset);
+          checkGenericFunctionTypeArgument(node.keyType, node.fileOffset);
+          checkGenericFunctionTypeArgument(node.valueType, node.fileOffset);
         }
       }
     }
@@ -3080,7 +3007,7 @@
     Link<NullAwareGuard> nullAwareGuards = result.nullAwareGuards;
     Expression receiver = result.nullAwareAction;
     DartType receiverType = result.nullAwareActionType;
-    return inferrer.inferMethodInvocation(
+    return inferMethodInvocation(
         this,
         node.fileOffset,
         nullAwareGuards,
@@ -3100,7 +3027,7 @@
     Link<NullAwareGuard> nullAwareGuards = result.nullAwareGuards;
     Expression receiver = result.nullAwareAction;
     DartType receiverType = result.nullAwareActionType;
-    return inferrer.inferMethodInvocation(
+    return inferMethodInvocation(
         this,
         node.fileOffset,
         nullAwareGuards,
@@ -3115,16 +3042,14 @@
 
   @override
   ExpressionInferenceResult visitNot(Not node, DartType typeContext) {
-    InterfaceType boolType =
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+    InterfaceType boolType = coreTypes.boolRawType(libraryBuilder.nonNullable);
     ExpressionInferenceResult operandResult =
-        inferExpression(node.operand, boolType, !inferrer.isTopLevel);
-    Expression operand = inferrer
-        .ensureAssignableResult(boolType, operandResult,
+        inferExpression(node.operand, boolType, !isTopLevel);
+    Expression operand = ensureAssignableResult(boolType, operandResult,
             fileOffset: node.fileOffset)
         .expression;
     node.operand = operand..parent = node;
-    inferrer.flowAnalysis.logicalNot_end(node, node.operand);
+    flowAnalysis.logicalNot_end(node, node.operand);
     return new ExpressionInferenceResult(boolType, node);
   }
 
@@ -3132,7 +3057,7 @@
   ExpressionInferenceResult visitNullCheck(
       NullCheck node, DartType typeContext) {
     ExpressionInferenceResult operandResult = inferNullAwareExpression(
-        node.operand, inferrer.computeNullable(typeContext), true);
+        node.operand, computeNullable(typeContext), true);
 
     Link<NullAwareGuard> nullAwareGuards = operandResult.nullAwareGuards;
     Expression operand = operandResult.nullAwareAction;
@@ -3141,9 +3066,9 @@
     node.operand = operand..parent = node;
     reportNonNullableInNullAwareWarningIfNeeded(
         operandType, "!", node.operand.fileOffset);
-    inferrer.flowAnalysis.nonNullAssert_end(node.operand);
+    flowAnalysis.nonNullAssert_end(node.operand);
     DartType nonNullableResultType = operandType.toNonNull();
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         nonNullableResultType, node, nullAwareGuards);
   }
 
@@ -3153,12 +3078,11 @@
         inferSyntheticVariableNullAware(node.variable);
     reportNonNullableInNullAwareWarningIfNeeded(
         node.variable.type, "?.", node.variable.fileOffset);
-    NullAwareGuard nullAwareGuard =
-        inferrer.createNullAwareGuard(node.variable);
+    NullAwareGuard nullAwareGuard = createNullAwareGuard(node.variable);
     ExpressionInferenceResult invocationResult = inferExpression(
         node.invocation, typeContext, true,
         isVoidAllowed: true);
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         invocationResult.inferredType,
         invocationResult.expression,
         nullAwareGuards.prepend(nullAwareGuard));
@@ -3170,14 +3094,11 @@
         inferSyntheticVariableNullAware(node.variable);
     reportNonNullableInNullAwareWarningIfNeeded(
         node.variable.type, "?.", node.variable.fileOffset);
-    NullAwareGuard nullAwareGuard =
-        inferrer.createNullAwareGuard(node.variable);
+    NullAwareGuard nullAwareGuard = createNullAwareGuard(node.variable);
     ExpressionInferenceResult readResult =
         inferExpression(node.read, typeContext, true);
-    return inferrer.createNullAwareExpressionInferenceResult(
-        readResult.inferredType,
-        readResult.expression,
-        nullAwareGuards.prepend(nullAwareGuard));
+    return createNullAwareExpressionInferenceResult(readResult.inferredType,
+        readResult.expression, nullAwareGuards.prepend(nullAwareGuard));
   }
 
   ExpressionInferenceResult visitNullAwarePropertySet(
@@ -3186,14 +3107,11 @@
         inferSyntheticVariableNullAware(node.variable);
     reportNonNullableInNullAwareWarningIfNeeded(
         node.variable.type, "?.", node.variable.fileOffset);
-    NullAwareGuard nullAwareGuard =
-        inferrer.createNullAwareGuard(node.variable);
+    NullAwareGuard nullAwareGuard = createNullAwareGuard(node.variable);
     ExpressionInferenceResult writeResult =
         inferExpression(node.write, typeContext, true);
-    return inferrer.createNullAwareExpressionInferenceResult(
-        writeResult.inferredType,
-        writeResult.expression,
-        nullAwareGuards.prepend(nullAwareGuard));
+    return createNullAwareExpressionInferenceResult(writeResult.inferredType,
+        writeResult.expression, nullAwareGuards.prepend(nullAwareGuard));
   }
 
   ExpressionInferenceResult visitNullAwareExtension(
@@ -3201,11 +3119,10 @@
     inferSyntheticVariable(node.variable);
     reportNonNullableInNullAwareWarningIfNeeded(
         node.variable.type, "?.", node.variable.fileOffset);
-    NullAwareGuard nullAwareGuard =
-        inferrer.createNullAwareGuard(node.variable);
+    NullAwareGuard nullAwareGuard = createNullAwareGuard(node.variable);
     ExpressionInferenceResult expressionResult =
         inferExpression(node.expression, const UnknownType(), true);
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         expressionResult.inferredType,
         expressionResult.expression,
         const Link<NullAwareGuard>().prepend(nullAwareGuard));
@@ -3288,8 +3205,8 @@
       writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
+      instrumentation?.record(
+          uriForInstrumentation,
           receiverVariable.fileOffset,
           'type',
           new InstrumentationValueForType(receiverType));
@@ -3305,12 +3222,12 @@
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
 
-    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget writeTarget = findInterfaceMember(
         receiverType, node.propertyName, node.writeOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         instrumented: true,
         includeExtensionMethods: true);
-    DartType writeType = inferrer.getSetterType(writeTarget, receiverType);
+    DartType writeType = getSetterType(writeTarget, receiverType);
 
     ExpressionInferenceResult binaryResult = _computeBinaryExpression(
         node.binaryOffset,
@@ -3321,7 +3238,7 @@
         node.rhs,
         null);
 
-    binaryResult = inferrer.ensureAssignableResult(writeType, binaryResult);
+    binaryResult = ensureAssignableResult(writeType, binaryResult);
     DartType binaryType = binaryResult.inferredType;
     Expression binary = binaryResult.expression;
 
@@ -3334,7 +3251,7 @@
       replacement = createLet(receiverVariable, replacement);
     }
     replacement.fileOffset = node.fileOffset;
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         binaryType, replacement, nullAwareGuards);
   }
 
@@ -3350,11 +3267,8 @@
 
     VariableDeclaration receiverVariable =
         createVariable(receiver, receiverType);
-    inferrer.instrumentation?.record(
-        inferrer.uriForInstrumentation,
-        receiverVariable.fileOffset,
-        'type',
-        new InstrumentationValueForType(receiverType));
+    instrumentation?.record(uriForInstrumentation, receiverVariable.fileOffset,
+        'type', new InstrumentationValueForType(receiverType));
     Expression readReceiver = createVariableGet(receiverVariable);
     Expression writeReceiver = createVariableGet(receiverVariable);
 
@@ -3368,19 +3282,19 @@
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
 
-    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget writeTarget = findInterfaceMember(
         receiverType, node.propertyName, receiver.fileOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         instrumented: true,
         includeExtensionMethods: true);
-    DartType writeContext = inferrer.getSetterType(writeTarget, receiverType);
+    DartType writeContext = getSetterType(writeTarget, receiverType);
 
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
+    flowAnalysis.ifNullExpression_rightBegin(read, readType);
     ExpressionInferenceResult rhsResult =
         inferExpression(node.rhs, writeContext, true, isVoidAllowed: true);
-    inferrer.flowAnalysis.ifNullExpression_end();
+    flowAnalysis.ifNullExpression_end();
 
-    rhsResult = inferrer.ensureAssignableResult(writeContext, rhsResult);
+    rhsResult = ensureAssignableResult(writeContext, rhsResult);
     Expression rhs = rhsResult.expression;
 
     DartType writeType = rhsResult.inferredType;
@@ -3389,9 +3303,8 @@
         forEffect: node.forEffect, valueType: writeType);
 
     DartType nonNullableReadType = readType.toNonNull();
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(
-            nonNullableReadType, writeType, inferrer.libraryBuilder.library);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        nonNullableReadType, writeType, libraryBuilder.library);
 
     Expression replacement;
     if (node.forEffect) {
@@ -3399,7 +3312,7 @@
       //
       //     let v1 = o in v1.a == null ? v1.a = b : null
       //
-      Expression equalsNull = inferrer.createEqualsNull(node.fileOffset, read);
+      Expression equalsNull = createEqualsNull(node.fileOffset, read);
       ConditionalExpression conditional = new ConditionalExpression(equalsNull,
           write, new NullLiteral()..fileOffset = node.fileOffset, inferredType)
         ..fileOffset = node.fileOffset;
@@ -3412,10 +3325,10 @@
       //     let v1 = o in let v2 = v1.a in v2 == null ? v1.a = b : v2
       //
       VariableDeclaration readVariable = createVariable(read, readType);
-      Expression equalsNull = inferrer.createEqualsNull(
-          node.fileOffset, createVariableGet(readVariable));
+      Expression equalsNull =
+          createEqualsNull(node.fileOffset, createVariableGet(readVariable));
       VariableGet variableGet = createVariableGet(readVariable);
-      if (inferrer.libraryBuilder.isNonNullableByDefault &&
+      if (libraryBuilder.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
         variableGet.promotedType = nonNullableReadType;
       }
@@ -3427,7 +3340,7 @@
             ..fileOffset = node.fileOffset;
     }
 
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         inferredType, replacement, nullAwareGuards);
   }
 
@@ -3442,16 +3355,15 @@
     Expression read = readResult.nullAwareAction;
     DartType readType = readResult.nullAwareActionType;
 
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
+    flowAnalysis.ifNullExpression_rightBegin(read, readType);
     ExpressionInferenceResult writeResult =
         inferExpression(node.write, typeContext, true, isVoidAllowed: true);
-    inferrer.flowAnalysis.ifNullExpression_end();
+    flowAnalysis.ifNullExpression_end();
 
     DartType originalReadType = readType;
     DartType nonNullableReadType = originalReadType.toNonNull();
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(nonNullableReadType, writeResult.inferredType,
-            inferrer.libraryBuilder.library);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        nonNullableReadType, writeResult.inferredType, libraryBuilder.library);
 
     Expression replacement;
     if (node.forEffect) {
@@ -3459,7 +3371,7 @@
       //
       //     a == null ? a = b : null
       //
-      Expression equalsNull = inferrer.createEqualsNull(node.fileOffset, read);
+      Expression equalsNull = createEqualsNull(node.fileOffset, read);
       replacement = new ConditionalExpression(
           equalsNull,
           writeResult.expression,
@@ -3472,10 +3384,10 @@
       //      let v1 = a in v1 == null ? a = b : v1
       //
       VariableDeclaration readVariable = createVariable(read, readType);
-      Expression equalsNull = inferrer.createEqualsNull(
-          node.fileOffset, createVariableGet(readVariable));
+      Expression equalsNull =
+          createEqualsNull(node.fileOffset, createVariableGet(readVariable));
       VariableGet variableGet = createVariableGet(readVariable);
-      if (inferrer.libraryBuilder.isNonNullableByDefault &&
+      if (libraryBuilder.isNonNullableByDefault &&
           !identical(nonNullableReadType, originalReadType)) {
         variableGet.promotedType = nonNullableReadType;
       }
@@ -3485,7 +3397,7 @@
       replacement = new Let(readVariable, conditional)
         ..fileOffset = node.fileOffset;
     }
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         inferredType, replacement, nullAwareGuards);
   }
 
@@ -3498,22 +3410,22 @@
     Expression receiver = receiverResult.nullAwareAction;
     DartType receiverType = receiverResult.nullAwareActionType;
 
-    ObjectAccessTarget indexGetTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget indexGetTarget = findInterfaceMember(
         receiverType, indexGetName, node.fileOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
-    DartType indexType = inferrer.getIndexKeyType(indexGetTarget, receiverType);
+    DartType indexType = getIndexKeyType(indexGetTarget, receiverType);
 
     MethodContravarianceCheckKind readCheckKind =
-        inferrer.preCheckInvocationContravariance(receiverType, indexGetTarget,
+        preCheckInvocationContravariance(receiverType, indexGetTarget,
             isThisReceiver: node.receiver is ThisExpression);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, indexType, true, isVoidAllowed: true);
 
     Expression index =
-        inferrer.ensureAssignableResult(indexType, indexResult).expression;
+        ensureAssignableResult(indexType, indexResult).expression;
 
     ExpressionInferenceResult replacement = _computeIndexGet(
         node.fileOffset,
@@ -3523,7 +3435,7 @@
         index,
         indexType,
         readCheckKind);
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         replacement.inferredType, replacement.expression, nullAwareGuards);
   }
 
@@ -3542,20 +3454,19 @@
       receiver = createVariableGet(receiverVariable);
     }
 
-    ObjectAccessTarget indexSetTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget indexSetTarget = findInterfaceMember(
         receiverType, indexSetName, node.fileOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
-    DartType indexType = inferrer.getIndexKeyType(indexSetTarget, receiverType);
-    DartType valueType =
-        inferrer.getIndexSetValueType(indexSetTarget, receiverType);
+    DartType indexType = getIndexKeyType(indexSetTarget, receiverType);
+    DartType valueType = getIndexSetValueType(indexSetTarget, receiverType);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, indexType, true, isVoidAllowed: true);
 
     Expression index =
-        inferrer.ensureAssignableResult(indexType, indexResult).expression;
+        ensureAssignableResult(indexType, indexResult).expression;
 
     VariableDeclaration? indexVariable;
     if (!node.forEffect && !isPureExpression(index)) {
@@ -3565,7 +3476,7 @@
 
     ExpressionInferenceResult valueResult =
         inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
 
     VariableDeclaration? valueVariable;
@@ -3604,7 +3515,7 @@
       }
     }
     replacement.fileOffset = node.fileOffset;
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         inferredType, replacement, nullAwareGuards);
   }
 
@@ -3615,16 +3526,14 @@
             isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
-    DartType indexType =
-        inferrer.getIndexKeyType(indexSetTarget, inferrer.thisType!);
-    DartType valueType =
-        inferrer.getIndexSetValueType(indexSetTarget, inferrer.thisType!);
+    DartType indexType = getIndexKeyType(indexSetTarget, thisType!);
+    DartType valueType = getIndexSetValueType(indexSetTarget, thisType!);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, indexType, true, isVoidAllowed: true);
 
     Expression index =
-        inferrer.ensureAssignableResult(indexType, indexResult).expression;
+        ensureAssignableResult(indexType, indexResult).expression;
 
     VariableDeclaration? indexVariable;
     if (!isPureExpression(index)) {
@@ -3634,7 +3543,7 @@
 
     ExpressionInferenceResult valueResult =
         inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
 
     VariableDeclaration? valueVariable;
@@ -3653,14 +3562,10 @@
 
     Expression assignment;
     if (indexSetTarget.isMissing) {
-      assignment =
-          inferrer.createMissingSuperIndexSet(node.fileOffset, index, value);
+      assignment = createMissingSuperIndexSet(node.fileOffset, index, value);
     } else {
       assert(indexSetTarget.isInstanceMember || indexSetTarget.isObjectMember);
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.fileOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.fileOffset, 'target',
           new InstrumentationValueForMember(node.setter!));
       assignment = new SuperMethodInvocation(
           indexSetName,
@@ -3687,16 +3592,16 @@
         node.receiver, const UnknownType(), true,
         isVoidAllowed: false);
 
-    List<DartType> extensionTypeArguments =
-        inferrer.computeExtensionTypeArgument(node.extension,
-            node.explicitTypeArguments, receiverResult.inferredType);
+    List<DartType> extensionTypeArguments = computeExtensionTypeArgument(
+        node.extension,
+        node.explicitTypeArguments,
+        receiverResult.inferredType);
 
-    DartType receiverType = inferrer.getExtensionReceiverType(
-        node.extension, extensionTypeArguments);
+    DartType receiverType =
+        getExtensionReceiverType(node.extension, extensionTypeArguments);
 
-    Expression receiver = inferrer
-        .ensureAssignableResult(receiverType, receiverResult)
-        .expression;
+    Expression receiver =
+        ensureAssignableResult(receiverType, receiverResult).expression;
 
     VariableDeclaration? receiverVariable;
     if (!isPureExpression(receiver)) {
@@ -3707,18 +3612,18 @@
     ObjectAccessTarget target = new ExtensionAccessTarget(
         node.setter, null, ProcedureKind.Operator, extensionTypeArguments);
 
-    DartType indexType = inferrer.getIndexKeyType(target, receiverType);
-    DartType valueType = inferrer.getIndexSetValueType(target, receiverType);
+    DartType indexType = getIndexKeyType(target, receiverType);
+    DartType valueType = getIndexSetValueType(target, receiverType);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, indexType, true, isVoidAllowed: true);
 
     Expression index =
-        inferrer.ensureAssignableResult(indexType, indexResult).expression;
+        ensureAssignableResult(indexType, indexResult).expression;
 
     ExpressionInferenceResult valueResult =
         inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
 
     VariableDeclaration? valueVariable;
@@ -3773,26 +3678,24 @@
       writeReceiver = createVariableGet(receiverVariable);
     }
 
-    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget readTarget = findInterfaceMember(
         receiverType, indexGetName, node.readOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
-    MethodContravarianceCheckKind checkKind =
-        inferrer.preCheckInvocationContravariance(receiverType, readTarget,
-            isThisReceiver: node.receiver is ThisExpression);
+    MethodContravarianceCheckKind checkKind = preCheckInvocationContravariance(
+        receiverType, readTarget,
+        isThisReceiver: node.receiver is ThisExpression);
 
-    DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
+    DartType readIndexType = getIndexKeyType(readTarget, receiverType);
 
-    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget writeTarget = findInterfaceMember(
         receiverType, indexSetName, node.writeOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
-    DartType writeIndexType =
-        inferrer.getIndexKeyType(writeTarget, receiverType);
-    DartType valueType =
-        inferrer.getIndexSetValueType(writeTarget, receiverType);
+    DartType writeIndexType = getIndexKeyType(writeTarget, receiverType);
+    DartType valueType = getIndexSetValueType(writeTarget, receiverType);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -3800,7 +3703,7 @@
     VariableDeclaration? indexVariable;
     Expression readIndex = indexResult.expression;
     Map<DartType, NonPromotionReason> Function() whyNotPromotedIndex =
-        inferrer.flowAnalysis.whyNotPromoted(readIndex);
+        flowAnalysis.whyNotPromoted(readIndex);
     Expression writeIndex;
     if (isPureExpression(readIndex)) {
       writeIndex = clonePureExpression(readIndex);
@@ -3810,7 +3713,7 @@
       writeIndex = createVariableGet(indexVariable);
     }
 
-    readIndex = inferrer.ensureAssignable(
+    readIndex = ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex,
         whyNotPromoted: whyNotPromotedIndex);
 
@@ -3826,22 +3729,21 @@
         readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
+    flowAnalysis.ifNullExpression_rightBegin(read, readType);
 
-    writeIndex = inferrer.ensureAssignable(
+    writeIndex = ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex,
         whyNotPromoted: whyNotPromotedIndex);
 
     ExpressionInferenceResult valueResult =
         inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
-    inferrer.flowAnalysis.ifNullExpression_end();
+    flowAnalysis.ifNullExpression_end();
 
     DartType nonNullableReadType = readType.toNonNull();
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
-            inferrer.libraryBuilder.library);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        nonNullableReadType, valueResult.inferredType, libraryBuilder.library);
 
     VariableDeclaration? valueVariable;
     Expression? returnedValue;
@@ -3880,7 +3782,7 @@
       //     let indexVariable = a in
       //         o[indexVariable] == null ? o.[]=(indexVariable, b) : null
       //
-      Expression equalsNull = inferrer.createEqualsNull(node.testOffset, read);
+      Expression equalsNull = createEqualsNull(node.testOffset, read);
       ConditionalExpression conditional = new ConditionalExpression(equalsNull,
           write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
@@ -3911,12 +3813,12 @@
       //
       //
       VariableDeclaration readVariable = createVariable(read, readType);
-      Expression equalsNull = inferrer.createEqualsNull(
-          node.testOffset, createVariableGet(readVariable));
+      Expression equalsNull =
+          createEqualsNull(node.testOffset, createVariableGet(readVariable));
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
       VariableGet variableGet = createVariableGet(readVariable);
-      if (inferrer.libraryBuilder.isNonNullableByDefault &&
+      if (libraryBuilder.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
         variableGet.promotedType = nonNullableReadType;
       }
@@ -3940,7 +3842,7 @@
     } else {
       replacement = inner;
     }
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         inferredType, replacement, nullAwareGuards);
   }
 
@@ -3951,21 +3853,18 @@
             isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
-    DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType!);
+    DartType readType = getReturnType(readTarget, thisType!);
     reportNonNullableInNullAwareWarningIfNeeded(
         readType, "??=", node.readOffset);
-    DartType readIndexType =
-        inferrer.getIndexKeyType(readTarget, inferrer.thisType!);
+    DartType readIndexType = getIndexKeyType(readTarget, thisType!);
 
     ObjectAccessTarget writeTarget = node.setter != null
         ? new ObjectAccessTarget.interfaceMember(node.setter!,
             isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
-    DartType writeIndexType =
-        inferrer.getIndexKeyType(writeTarget, inferrer.thisType!);
-    DartType valueType =
-        inferrer.getIndexSetValueType(writeTarget, inferrer.thisType!);
+    DartType writeIndexType = getIndexKeyType(writeTarget, thisType!);
+    DartType valueType = getIndexSetValueType(writeTarget, thisType!);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -3981,22 +3880,19 @@
       writeIndex = createVariableGet(indexVariable);
     }
 
-    readIndex = inferrer.ensureAssignable(
-        readIndexType, indexResult.inferredType, readIndex);
+    readIndex =
+        ensureAssignable(readIndexType, indexResult.inferredType, readIndex);
 
-    writeIndex = inferrer.ensureAssignable(
-        writeIndexType, indexResult.inferredType, writeIndex);
+    writeIndex =
+        ensureAssignable(writeIndexType, indexResult.inferredType, writeIndex);
 
     Expression read;
 
     if (readTarget.isMissing) {
-      read = inferrer.createMissingSuperIndexGet(node.readOffset, readIndex);
+      read = createMissingSuperIndexGet(node.readOffset, readIndex);
     } else {
       assert(readTarget.isInstanceMember || readTarget.isObjectMember);
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.readOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.readOffset, 'target',
           new InstrumentationValueForMember(node.getter!));
       read = new SuperMethodInvocation(
           indexGetName,
@@ -4008,17 +3904,16 @@
         ..fileOffset = node.readOffset;
     }
 
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
+    flowAnalysis.ifNullExpression_rightBegin(read, readType);
     ExpressionInferenceResult valueResult =
         inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
-    inferrer.flowAnalysis.ifNullExpression_end();
+    flowAnalysis.ifNullExpression_end();
 
     DartType nonNullableReadType = readType.toNonNull();
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
-            inferrer.libraryBuilder.library);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        nonNullableReadType, valueResult.inferredType, libraryBuilder.library);
 
     VariableDeclaration? valueVariable;
     Expression? returnedValue;
@@ -4035,14 +3930,10 @@
     Expression write;
 
     if (writeTarget.isMissing) {
-      write = inferrer.createMissingSuperIndexSet(
-          node.writeOffset, writeIndex, value);
+      write = createMissingSuperIndexSet(node.writeOffset, writeIndex, value);
     } else {
       assert(writeTarget.isInstanceMember || writeTarget.isObjectMember);
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.writeOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.writeOffset, 'target',
           new InstrumentationValueForMember(node.setter!));
       write = new SuperMethodInvocation(
           indexSetName,
@@ -4060,7 +3951,7 @@
       //        super[v1] == null ? super.[]=(v1, b) : null
       //
       assert(valueVariable == null);
-      Expression equalsNull = inferrer.createEqualsNull(node.testOffset, read);
+      Expression equalsNull = createEqualsNull(node.testOffset, read);
       replacement = new ConditionalExpression(equalsNull, write,
           new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
@@ -4077,12 +3968,12 @@
       //
 
       VariableDeclaration readVariable = createVariable(read, readType);
-      Expression equalsNull = inferrer.createEqualsNull(
-          node.testOffset, createVariableGet(readVariable));
+      Expression equalsNull =
+          createEqualsNull(node.testOffset, createVariableGet(readVariable));
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
       VariableGet readVariableGet = createVariableGet(readVariable);
-      if (inferrer.libraryBuilder.isNonNullableByDefault &&
+      if (libraryBuilder.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
         readVariableGet.promotedType = nonNullableReadType;
       }
@@ -4107,16 +3998,16 @@
         node.receiver, const UnknownType(), true,
         isVoidAllowed: false);
 
-    List<DartType> extensionTypeArguments =
-        inferrer.computeExtensionTypeArgument(node.extension,
-            node.explicitTypeArguments, receiverResult.inferredType);
+    List<DartType> extensionTypeArguments = computeExtensionTypeArgument(
+        node.extension,
+        node.explicitTypeArguments,
+        receiverResult.inferredType);
 
-    DartType receiverType = inferrer.getExtensionReceiverType(
-        node.extension, extensionTypeArguments);
+    DartType receiverType =
+        getExtensionReceiverType(node.extension, extensionTypeArguments);
 
-    Expression receiver = inferrer
-        .ensureAssignableResult(receiverType, receiverResult)
-        .expression;
+    Expression receiver =
+        ensureAssignableResult(receiverType, receiverResult).expression;
 
     VariableDeclaration? receiverVariable;
     Expression readReceiver;
@@ -4135,17 +4026,15 @@
             node.getter!, null, ProcedureKind.Operator, extensionTypeArguments)
         : const ObjectAccessTarget.missing();
 
-    DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
+    DartType readIndexType = getIndexKeyType(readTarget, receiverType);
 
     ObjectAccessTarget writeTarget = node.setter != null
         ? new ExtensionAccessTarget(
             node.setter!, null, ProcedureKind.Operator, extensionTypeArguments)
         : const ObjectAccessTarget.missing();
 
-    DartType writeIndexType =
-        inferrer.getIndexKeyType(writeTarget, receiverType);
-    DartType valueType =
-        inferrer.getIndexSetValueType(writeTarget, receiverType);
+    DartType writeIndexType = getIndexKeyType(writeTarget, receiverType);
+    DartType valueType = getIndexSetValueType(writeTarget, receiverType);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -4161,8 +4050,8 @@
       writeIndex = createVariableGet(indexVariable);
     }
 
-    readIndex = inferrer.ensureAssignable(
-        readIndexType, indexResult.inferredType, readIndex);
+    readIndex =
+        ensureAssignable(readIndexType, indexResult.inferredType, readIndex);
 
     ExpressionInferenceResult readResult = _computeIndexGet(
         node.readOffset,
@@ -4176,21 +4065,20 @@
         readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
+    flowAnalysis.ifNullExpression_rightBegin(read, readType);
 
-    writeIndex = inferrer.ensureAssignable(
-        writeIndexType, indexResult.inferredType, writeIndex);
+    writeIndex =
+        ensureAssignable(writeIndexType, indexResult.inferredType, writeIndex);
 
     ExpressionInferenceResult valueResult =
         inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
-    inferrer.flowAnalysis.ifNullExpression_end();
+    flowAnalysis.ifNullExpression_end();
 
     DartType nonNullableReadType = readType.toNonNull();
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
-            inferrer.libraryBuilder.library);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        nonNullableReadType, valueResult.inferredType, libraryBuilder.library);
 
     VariableDeclaration? valueVariable;
     Expression? returnedValue;
@@ -4224,7 +4112,7 @@
       //          ? receiverVariable.[]=(indexVariable, b) : null
       //
       assert(valueVariable == null);
-      Expression equalsNull = inferrer.createEqualsNull(node.testOffset, read);
+      Expression equalsNull = createEqualsNull(node.testOffset, read);
       replacement = new ConditionalExpression(equalsNull, write,
           new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
@@ -4242,12 +4130,12 @@
       //        : readVariable
       //
       VariableDeclaration readVariable = createVariable(read, readType);
-      Expression equalsNull = inferrer.createEqualsNull(
-          node.testOffset, createVariableGet(readVariable));
+      Expression equalsNull =
+          createEqualsNull(node.testOffset, createVariableGet(readVariable));
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
       VariableGet readVariableGet = createVariableGet(readVariable);
-      if (inferrer.libraryBuilder.isNonNullableByDefault &&
+      if (libraryBuilder.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
         readVariableGet.promotedType = nonNullableReadType;
       }
@@ -4287,8 +4175,8 @@
     // ignore: unnecessary_null_comparison
     assert(isNot != null);
     EqualityInfo<VariableDeclaration, DartType>? equalityInfo =
-        inferrer.flowAnalysis.equalityOperand_end(left, leftType);
-    bool typeNeeded = !inferrer.isTopLevel;
+        flowAnalysis.equalityOperand_end(left, leftType);
+    bool typeNeeded = !isTopLevel;
 
     Expression? equals;
     ExpressionInferenceResult rightResult = inferExpression(
@@ -4304,18 +4192,17 @@
       if (isNot) {
         equals = new Not(equals)..fileOffset = fileOffset;
       }
-      inferrer.flowAnalysis.equalityOperation_end(
+      flowAnalysis.equalityOperation_end(
           equals,
           equalityInfo,
-          inferrer.flowAnalysis.equalityOperand_end(
+          flowAnalysis.equalityOperand_end(
               rightResult.expression, rightResult.inferredType),
           notEqual: isNot);
       return new ExpressionInferenceResult(
-          inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable),
-          equals);
+          coreTypes.boolRawType(libraryBuilder.nonNullable), equals);
     }
 
-    ObjectAccessTarget equalsTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget equalsTarget = findInterfaceMember(
         leftType, equalsName, fileOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
@@ -4326,18 +4213,14 @@
             equalsTarget.isNever,
         "Unexpected equals target $equalsTarget for "
         "$left ($leftType) == $right.");
-    if (inferrer.instrumentation != null && leftType == const DynamicType()) {
-      inferrer.instrumentation!.record(
-          inferrer.uriForInstrumentation,
-          fileOffset,
-          'target',
+    if (instrumentation != null && leftType == const DynamicType()) {
+      instrumentation!.record(uriForInstrumentation, fileOffset, 'target',
           new InstrumentationValueForMember(equalsTarget.member!));
     }
     DartType rightType =
-        inferrer.getPositionalParameterTypeForTarget(equalsTarget, leftType, 0);
-    rightResult = inferrer.ensureAssignableResult(
-        rightType.withDeclaredNullability(inferrer.libraryBuilder.nullable),
-        rightResult,
+        getPositionalParameterTypeForTarget(equalsTarget, leftType, 0);
+    rightResult = ensureAssignableResult(
+        rightType.withDeclaredNullability(libraryBuilder.nullable), rightResult,
         errorTemplate: templateArgumentTypeNotAssignable,
         nullabilityErrorTemplate: templateArgumentTypeNotAssignableNullability,
         nullabilityPartErrorTemplate:
@@ -4349,8 +4232,7 @@
     right = rightResult.expression;
 
     if (equalsTarget.isInstanceMember || equalsTarget.isObjectMember) {
-      FunctionType functionType =
-          inferrer.getFunctionType(equalsTarget, leftType);
+      FunctionType functionType = getFunctionType(equalsTarget, leftType);
       equals = new EqualsCall(left, right,
           functionType: functionType,
           interfaceTarget: equalsTarget.member as Procedure)
@@ -4361,10 +4243,9 @@
     } else {
       assert(equalsTarget.isNever);
       FunctionType functionType = new FunctionType([const DynamicType()],
-          const NeverType.nonNullable(), inferrer.libraryBuilder.nonNullable);
+          const NeverType.nonNullable(), libraryBuilder.nonNullable);
       // Ensure operator == member even for `Never`.
-      Member target = inferrer
-          .findInterfaceMember(const DynamicType(), equalsName, -1,
+      Member target = findInterfaceMember(const DynamicType(), equalsName, -1,
               instrumented: false,
               callSiteAccessKind: CallSiteAccessKind.operatorInvocation)
           .member!;
@@ -4376,17 +4257,13 @@
       }
     }
 
-    inferrer.flowAnalysis.equalityOperation_end(
-        equals,
-        equalityInfo,
-        inferrer.flowAnalysis
-            .equalityOperand_end(right, rightResult.inferredType),
+    flowAnalysis.equalityOperation_end(equals, equalityInfo,
+        flowAnalysis.equalityOperand_end(right, rightResult.inferredType),
         notEqual: isNot);
     return new ExpressionInferenceResult(
         equalsTarget.isNever
             ? const NeverType.nonNullable()
-            : inferrer.coreTypes
-                .boolRawType(inferrer.libraryBuilder.nonNullable),
+            : coreTypes.boolRawType(libraryBuilder.nonNullable),
         equals);
   }
 
@@ -4406,30 +4283,30 @@
       Map<DartType, NonPromotionReason> Function()? whyNotPromoted) {
     assert(binaryName != equalsName);
 
-    ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget binaryTarget = findInterfaceMember(
         leftType, binaryName, fileOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
     MethodContravarianceCheckKind binaryCheckKind =
-        inferrer.preCheckInvocationContravariance(leftType, binaryTarget,
+        preCheckInvocationContravariance(leftType, binaryTarget,
             isThisReceiver: false);
 
-    DartType binaryType = inferrer.getReturnType(binaryTarget, leftType);
+    DartType binaryType = getReturnType(binaryTarget, leftType);
     DartType rightType =
-        inferrer.getPositionalParameterTypeForTarget(binaryTarget, leftType, 0);
+        getPositionalParameterTypeForTarget(binaryTarget, leftType, 0);
 
-    bool isSpecialCasedBinaryOperator = inferrer
-        .isSpecialCasedBinaryOperatorForReceiverType(binaryTarget, leftType);
+    bool isSpecialCasedBinaryOperator =
+        isSpecialCasedBinaryOperatorForReceiverType(binaryTarget, leftType);
 
-    bool typeNeeded = !inferrer.isTopLevel || isSpecialCasedBinaryOperator;
+    bool typeNeeded = !isTopLevel || isSpecialCasedBinaryOperator;
 
     DartType rightContextType = rightType;
     if (isSpecialCasedBinaryOperator) {
-      rightContextType = inferrer.typeSchemaEnvironment
-          .getContextTypeOfSpecialCasedBinaryOperator(
+      rightContextType =
+          typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
               contextType, leftType, rightType,
-              isNonNullableByDefault: inferrer.isNonNullableByDefault);
+              isNonNullableByDefault: isNonNullableByDefault);
     }
 
     ExpressionInferenceResult rightResult = inferExpression(
@@ -4438,34 +4315,31 @@
     if (identical(rightResult.inferredType, noInferredType)) {
       assert(!typeNeeded,
           "Missing right type for overloaded arithmetic operator.");
-      return new ExpressionInferenceResult(
-          binaryType,
-          inferrer.engine.forest
-              .createBinary(fileOffset, left, binaryName, right));
+      return new ExpressionInferenceResult(binaryType,
+          engine.forest.createBinary(fileOffset, left, binaryName, right));
     }
 
-    rightResult = inferrer.ensureAssignableResult(rightType, rightResult);
+    rightResult = ensureAssignableResult(rightType, rightResult);
     right = rightResult.expression;
 
     if (isSpecialCasedBinaryOperator) {
-      binaryType = inferrer.typeSchemaEnvironment
-          .getTypeOfSpecialCasedBinaryOperator(
-              leftType, rightResult.inferredType,
-              isNonNullableByDefault: inferrer.isNonNullableByDefault);
+      binaryType = typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
+          leftType, rightResult.inferredType,
+          isNonNullableByDefault: isNonNullableByDefault);
     }
 
-    if (!inferrer.isNonNullableByDefault) {
+    if (!isNonNullableByDefault) {
       binaryType = legacyErasure(binaryType);
     }
 
     Expression binary;
     switch (binaryTarget.kind) {
       case ObjectAccessTargetKind.missing:
-        binary = inferrer.createMissingBinary(
-            fileOffset, left, leftType, binaryName, right);
+        binary =
+            createMissingBinary(fileOffset, left, leftType, binaryName, right);
         break;
       case ObjectAccessTargetKind.ambiguous:
-        binary = inferrer.createMissingBinary(
+        binary = createMissingBinary(
             fileOffset, left, leftType, binaryName, right,
             extensionAccessCandidates: binaryTarget.candidates);
         break;
@@ -4520,12 +4394,9 @@
       case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         if ((binaryTarget.isInstanceMember || binaryTarget.isObjectMember) &&
-            inferrer.instrumentation != null &&
+            instrumentation != null &&
             leftType == const DynamicType()) {
-          inferrer.instrumentation!.record(
-              inferrer.uriForInstrumentation,
-              fileOffset,
-              'target',
+          instrumentation!.record(uriForInstrumentation, fileOffset, 'target',
               new InstrumentationValueForMember(binaryTarget.member!));
         }
 
@@ -4538,39 +4409,36 @@
             ])
               ..fileOffset = fileOffset,
             functionType: new FunctionType(
-                [rightType], binaryType, inferrer.libraryBuilder.nonNullable),
+                [rightType], binaryType, libraryBuilder.nonNullable),
             interfaceTarget: binaryTarget.member as Procedure)
           ..fileOffset = fileOffset;
 
         if (binaryCheckKind ==
             MethodContravarianceCheckKind.checkMethodReturn) {
-          if (inferrer.instrumentation != null) {
-            inferrer.instrumentation!.record(
-                inferrer.uriForInstrumentation,
-                fileOffset,
-                'checkReturn',
-                new InstrumentationValueForType(binaryType));
+          if (instrumentation != null) {
+            instrumentation!.record(uriForInstrumentation, fileOffset,
+                'checkReturn', new InstrumentationValueForType(binaryType));
           }
           binary = new AsExpression(binary, binaryType)
             ..isTypeError = true
             ..isCovarianceCheck = true
-            ..isForNonNullableByDefault = inferrer.isNonNullableByDefault
+            ..isForNonNullableByDefault = isNonNullableByDefault
             ..fileOffset = fileOffset;
         }
         break;
     }
 
-    if (!inferrer.isTopLevel && binaryTarget.isNullable) {
-      List<LocatedMessage>? context = inferrer.getWhyNotPromotedContext(
+    if (!isTopLevel && binaryTarget.isNullable) {
+      List<LocatedMessage>? context = getWhyNotPromotedContext(
           whyNotPromoted?.call(),
           binary,
           (type) => !type.isPotentiallyNullable);
       return new ExpressionInferenceResult(
           binaryType,
-          inferrer.helper.wrapInProblem(
+          helper.wrapInProblem(
               binary,
               templateNullableOperatorCallError.withArguments(
-                  binaryName.text, leftType, inferrer.isNonNullableByDefault),
+                  binaryName.text, leftType, isNonNullableByDefault),
               binary.fileOffset,
               binaryName.text.length,
               context: context));
@@ -4589,25 +4457,25 @@
       DartType expressionType,
       Name unaryName,
       Map<DartType, NonPromotionReason> Function() whyNotPromoted) {
-    ObjectAccessTarget unaryTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget unaryTarget = findInterfaceMember(
         expressionType, unaryName, fileOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
     MethodContravarianceCheckKind unaryCheckKind =
-        inferrer.preCheckInvocationContravariance(expressionType, unaryTarget,
+        preCheckInvocationContravariance(expressionType, unaryTarget,
             isThisReceiver: false);
 
-    DartType unaryType = inferrer.getReturnType(unaryTarget, expressionType);
+    DartType unaryType = getReturnType(unaryTarget, expressionType);
 
     Expression unary;
     switch (unaryTarget.kind) {
       case ObjectAccessTargetKind.missing:
-        unary = inferrer.createMissingUnary(
+        unary = createMissingUnary(
             fileOffset, expression, expressionType, unaryName);
         break;
       case ObjectAccessTargetKind.ambiguous:
-        unary = inferrer.createMissingUnary(
+        unary = createMissingUnary(
             fileOffset, expression, expressionType, unaryName,
             extensionAccessCandidates: unaryTarget.candidates);
         break;
@@ -4643,54 +4511,48 @@
       case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         if ((unaryTarget.isInstanceMember || unaryTarget.isObjectMember) &&
-            inferrer.instrumentation != null &&
+            instrumentation != null &&
             expressionType == const DynamicType()) {
-          inferrer.instrumentation!.record(
-              inferrer.uriForInstrumentation,
-              fileOffset,
-              'target',
+          instrumentation!.record(uriForInstrumentation, fileOffset, 'target',
               new InstrumentationValueForMember(unaryTarget.member!));
         }
 
         unary = new InstanceInvocation(InstanceAccessKind.Instance, expression,
             unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset,
             functionType: new FunctionType(
-                <DartType>[], unaryType, inferrer.libraryBuilder.nonNullable),
+                <DartType>[], unaryType, libraryBuilder.nonNullable),
             interfaceTarget: unaryTarget.member as Procedure)
           ..fileOffset = fileOffset;
 
         if (unaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-          if (inferrer.instrumentation != null) {
-            inferrer.instrumentation!.record(
-                inferrer.uriForInstrumentation,
-                fileOffset,
-                'checkReturn',
-                new InstrumentationValueForType(expressionType));
+          if (instrumentation != null) {
+            instrumentation!.record(uriForInstrumentation, fileOffset,
+                'checkReturn', new InstrumentationValueForType(expressionType));
           }
           unary = new AsExpression(unary, unaryType)
             ..isTypeError = true
             ..isCovarianceCheck = true
-            ..isForNonNullableByDefault = inferrer.isNonNullableByDefault
+            ..isForNonNullableByDefault = isNonNullableByDefault
             ..fileOffset = fileOffset;
         }
         break;
     }
 
-    if (!inferrer.isNonNullableByDefault) {
+    if (!isNonNullableByDefault) {
       unaryType = legacyErasure(unaryType);
     }
 
-    if (!inferrer.isTopLevel && unaryTarget.isNullable) {
-      List<LocatedMessage>? context = inferrer.getWhyNotPromotedContext(
+    if (!isTopLevel && unaryTarget.isNullable) {
+      List<LocatedMessage>? context = getWhyNotPromotedContext(
           whyNotPromoted(), unary, (type) => !type.isPotentiallyNullable);
       // TODO(johnniwinther): Special case 'unary-' in messages. It should
       // probably be referred to as "Unary operator '-' ...".
       return new ExpressionInferenceResult(
           unaryType,
-          inferrer.helper.wrapInProblem(
+          helper.wrapInProblem(
               unary,
-              templateNullableOperatorCallError.withArguments(unaryName.text,
-                  expressionType, inferrer.isNonNullableByDefault),
+              templateNullableOperatorCallError.withArguments(
+                  unaryName.text, expressionType, isNonNullableByDefault),
               unary.fileOffset,
               unaryName == unaryMinusName ? 1 : unaryName.text.length,
               context: context));
@@ -4713,14 +4575,14 @@
       DartType indexType,
       MethodContravarianceCheckKind readCheckKind) {
     Expression read;
-    DartType readType = inferrer.getReturnType(readTarget, receiverType);
+    DartType readType = getReturnType(readTarget, receiverType);
     switch (readTarget.kind) {
       case ObjectAccessTargetKind.missing:
-        read = inferrer.createMissingIndexGet(
+        read = createMissingIndexGet(
             fileOffset, readReceiver, receiverType, readIndex);
         break;
       case ObjectAccessTargetKind.ambiguous:
-        read = inferrer.createMissingIndexGet(
+        read = createMissingIndexGet(
             fileOffset, readReceiver, receiverType, readIndex,
             extensionAccessCandidates: readTarget.candidates);
         break;
@@ -4796,37 +4658,34 @@
             ])
               ..fileOffset = fileOffset,
             functionType: new FunctionType(
-                [indexType], readType, inferrer.libraryBuilder.nonNullable),
+                [indexType], readType, libraryBuilder.nonNullable),
             interfaceTarget: readTarget.member as Procedure)
           ..fileOffset = fileOffset;
         if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-          if (inferrer.instrumentation != null) {
-            inferrer.instrumentation!.record(
-                inferrer.uriForInstrumentation,
-                fileOffset,
-                'checkReturn',
-                new InstrumentationValueForType(readType));
+          if (instrumentation != null) {
+            instrumentation!.record(uriForInstrumentation, fileOffset,
+                'checkReturn', new InstrumentationValueForType(readType));
           }
           read = new AsExpression(read, readType)
             ..isTypeError = true
             ..isCovarianceCheck = true
-            ..isForNonNullableByDefault = inferrer.isNonNullableByDefault
+            ..isForNonNullableByDefault = isNonNullableByDefault
             ..fileOffset = fileOffset;
         }
         break;
     }
 
-    if (!inferrer.isNonNullableByDefault) {
+    if (!isNonNullableByDefault) {
       readType = legacyErasure(readType);
     }
 
-    if (!inferrer.isTopLevel && readTarget.isNullable) {
+    if (!isTopLevel && readTarget.isNullable) {
       return new ExpressionInferenceResult(
           readType,
-          inferrer.helper.wrapInProblem(
+          helper.wrapInProblem(
               read,
-              templateNullableOperatorCallError.withArguments(indexGetName.text,
-                  receiverType, inferrer.isNonNullableByDefault),
+              templateNullableOperatorCallError.withArguments(
+                  indexGetName.text, receiverType, isNonNullableByDefault),
               read.fileOffset,
               noLength));
     }
@@ -4851,12 +4710,12 @@
     Expression write;
     switch (writeTarget.kind) {
       case ObjectAccessTargetKind.missing:
-        write = inferrer.createMissingIndexSet(
+        write = createMissingIndexSet(
             fileOffset, receiver, receiverType, index, value,
             forEffect: true);
         break;
       case ObjectAccessTargetKind.ambiguous:
-        write = inferrer.createMissingIndexSet(
+        write = createMissingIndexSet(
             fileOffset, receiver, receiverType, index, value,
             forEffect: true, extensionAccessCandidates: writeTarget.candidates);
         break;
@@ -4916,16 +4775,16 @@
         write = new InstanceInvocation(kind, receiver, indexSetName,
             new Arguments(<Expression>[index, value])..fileOffset = fileOffset,
             functionType: new FunctionType([indexType, valueType],
-                const VoidType(), inferrer.libraryBuilder.nonNullable),
+                const VoidType(), libraryBuilder.nonNullable),
             interfaceTarget: writeTarget.member as Procedure)
           ..fileOffset = fileOffset;
         break;
     }
-    if (!inferrer.isTopLevel && writeTarget.isNullable) {
-      return inferrer.helper.wrapInProblem(
+    if (!isTopLevel && writeTarget.isNullable) {
+      return helper.wrapInProblem(
           write,
           templateNullableOperatorCallError.withArguments(
-              indexSetName.text, receiverType, inferrer.isNonNullableByDefault),
+              indexSetName.text, receiverType, isNonNullableByDefault),
           write.fileOffset,
           noLength);
     }
@@ -4950,22 +4809,22 @@
     // ignore: unnecessary_null_comparison
     assert(isThisReceiver != null);
 
-    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget readTarget = findInterfaceMember(
         receiverType, propertyName, fileOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.getterInvocation);
 
-    DartType readType = inferrer.getGetterType(readTarget, receiverType);
+    DartType readType = getGetterType(readTarget, receiverType);
 
     Expression read;
     ExpressionInferenceResult? readResult;
     switch (readTarget.kind) {
       case ObjectAccessTargetKind.missing:
-        read = inferrer.createMissingPropertyGet(
+        read = createMissingPropertyGet(
             fileOffset, receiver, receiverType, propertyName);
         break;
       case ObjectAccessTargetKind.ambiguous:
-        read = inferrer.createMissingPropertyGet(
+        read = createMissingPropertyGet(
             fileOffset, receiver, receiverType, propertyName,
             extensionAccessCandidates: readTarget.candidates);
         break;
@@ -4989,8 +4848,7 @@
                 ], types: readTarget.inferredExtensionTypeArguments)
                   ..fileOffset = fileOffset)
               ..fileOffset = fileOffset;
-            readResult =
-                inferrer.instantiateTearOff(readType, typeContext, read);
+            readResult = instantiateTearOff(readType, typeContext, read);
             break;
           case ProcedureKind.Setter:
           case ProcedureKind.Factory:
@@ -5019,10 +4877,10 @@
       case ObjectAccessTargetKind.nullableInstanceMember:
         Member member = readTarget.member!;
         if ((readTarget.isInstanceMember || readTarget.isObjectMember) &&
-            inferrer.instrumentation != null &&
+            instrumentation != null &&
             receiverType == const DynamicType()) {
-          inferrer.instrumentation!.record(inferrer.uriForInstrumentation,
-              fileOffset, 'target', new InstrumentationValueForMember(member));
+          instrumentation!.record(uriForInstrumentation, fileOffset, 'target',
+              new InstrumentationValueForMember(member));
         }
 
         InstanceAccessKind kind;
@@ -5053,9 +4911,9 @@
             !isThisReceiver) {
           Member interfaceMember = readTarget.member!;
           if (interfaceMember is Procedure) {
-            DartType typeToCheck = inferrer.isNonNullableByDefault
+            DartType typeToCheck = isNonNullableByDefault
                 ? interfaceMember.function
-                    .computeFunctionType(inferrer.libraryBuilder.nonNullable)
+                    .computeFunctionType(libraryBuilder.nonNullable)
                 : interfaceMember.function.returnType;
             checkReturn =
                 InferenceVisitorBase.returnedTypeParametersOccurNonCovariantly(
@@ -5067,39 +4925,36 @@
           }
         }
         if (checkReturn) {
-          if (inferrer.instrumentation != null) {
-            inferrer.instrumentation!.record(
-                inferrer.uriForInstrumentation,
-                fileOffset,
-                'checkReturn',
-                new InstrumentationValueForType(readType));
+          if (instrumentation != null) {
+            instrumentation!.record(uriForInstrumentation, fileOffset,
+                'checkReturn', new InstrumentationValueForType(readType));
           }
           read = new AsExpression(read, readType)
             ..isTypeError = true
             ..isCovarianceCheck = true
-            ..isForNonNullableByDefault = inferrer.isNonNullableByDefault
+            ..isForNonNullableByDefault = isNonNullableByDefault
             ..fileOffset = fileOffset;
         }
         if (member is Procedure && member.kind == ProcedureKind.Method) {
-          readResult = inferrer.instantiateTearOff(readType, typeContext, read);
+          readResult = instantiateTearOff(readType, typeContext, read);
         }
         break;
     }
 
-    if (!inferrer.isNonNullableByDefault) {
+    if (!isNonNullableByDefault) {
       readType = legacyErasure(readType);
     }
 
     readResult ??= new ExpressionInferenceResult(readType, read);
-    if (!inferrer.isTopLevel && readTarget.isNullable) {
-      readResult = inferrer.wrapExpressionInferenceResultInProblem(
+    if (!isTopLevel && readTarget.isNullable) {
+      readResult = wrapExpressionInferenceResultInProblem(
           readResult,
           templateNullablePropertyAccessError.withArguments(
-              propertyName.text, receiverType, inferrer.isNonNullableByDefault),
+              propertyName.text, receiverType, isNonNullableByDefault),
           read.fileOffset,
           propertyName.text.length,
-          context: inferrer.getWhyNotPromotedContext(
-              inferrer.flowAnalysis.whyNotPromoted(receiver)(),
+          context: getWhyNotPromotedContext(
+              flowAnalysis.whyNotPromoted(receiver)(),
               read,
               (type) => !type.isPotentiallyNullable));
     }
@@ -5133,12 +4988,12 @@
     Expression write;
     switch (writeTarget.kind) {
       case ObjectAccessTargetKind.missing:
-        write = inferrer.createMissingPropertySet(
+        write = createMissingPropertySet(
             fileOffset, receiver, receiverType, propertyName, value,
             forEffect: forEffect);
         break;
       case ObjectAccessTargetKind.ambiguous:
-        write = inferrer.createMissingPropertySet(
+        write = createMissingPropertySet(
             fileOffset, receiver, receiverType, propertyName, value,
             forEffect: forEffect,
             extensionAccessCandidates: writeTarget.candidates);
@@ -5207,11 +5062,11 @@
           ..fileOffset = fileOffset;
         break;
     }
-    if (!inferrer.isTopLevel && writeTarget.isNullable) {
-      return inferrer.helper.wrapInProblem(
+    if (!isTopLevel && writeTarget.isNullable) {
+      return helper.wrapInProblem(
           write,
           templateNullablePropertyAccessError.withArguments(
-              propertyName.text, receiverType, inferrer.isNonNullableByDefault),
+              propertyName.text, receiverType, isNonNullableByDefault),
           write.fileOffset,
           propertyName.text.length);
     }
@@ -5240,16 +5095,16 @@
       writeReceiver = createVariableGet(receiverVariable);
     }
 
-    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget readTarget = findInterfaceMember(
         receiverType, indexGetName, node.readOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
     MethodContravarianceCheckKind readCheckKind =
-        inferrer.preCheckInvocationContravariance(receiverType, readTarget,
+        preCheckInvocationContravariance(receiverType, readTarget,
             isThisReceiver: node.receiver is ThisExpression);
 
-    DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
+    DartType readIndexType = getIndexKeyType(readTarget, receiverType);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -5257,7 +5112,7 @@
     VariableDeclaration? indexVariable;
     Expression readIndex = indexResult.expression;
     Map<DartType, NonPromotionReason> Function() whyNotPromotedIndex =
-        inferrer.flowAnalysis.whyNotPromoted(readIndex);
+        flowAnalysis.whyNotPromoted(readIndex);
     Expression writeIndex;
     if (isPureExpression(readIndex)) {
       writeIndex = clonePureExpression(readIndex);
@@ -5267,7 +5122,7 @@
       writeIndex = createVariableGet(indexVariable);
     }
 
-    readIndex = inferrer.ensureAssignable(
+    readIndex = ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex,
         whyNotPromoted: whyNotPromotedIndex);
 
@@ -5293,16 +5148,14 @@
       left = read;
     }
 
-    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget writeTarget = findInterfaceMember(
         receiverType, indexSetName, node.writeOffset,
         includeExtensionMethods: true,
         callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
 
-    DartType writeIndexType =
-        inferrer.getIndexKeyType(writeTarget, receiverType);
+    DartType writeIndexType = getIndexKeyType(writeTarget, receiverType);
 
-    DartType valueType =
-        inferrer.getIndexSetValueType(writeTarget, receiverType);
+    DartType valueType = getIndexSetValueType(writeTarget, receiverType);
 
     ExpressionInferenceResult binaryResult = _computeBinaryExpression(
         node.binaryOffset,
@@ -5313,11 +5166,11 @@
         node.rhs,
         null);
 
-    writeIndex = inferrer.ensureAssignable(
+    writeIndex = ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex,
         whyNotPromoted: whyNotPromotedIndex);
 
-    binaryResult = inferrer.ensureAssignableResult(valueType, binaryResult,
+    binaryResult = ensureAssignableResult(valueType, binaryResult,
         fileOffset: node.fileOffset);
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
@@ -5392,7 +5245,7 @@
     } else {
       replacement = inner;
     }
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         node.forPostIncDec ? readType : binaryType,
         replacement,
         nullAwareGuards);
@@ -5412,8 +5265,7 @@
 
     VariableDeclaration? receiverVariable =
         createVariable(receiver, receiverType);
-    NullAwareGuard nullAwareGuard =
-        inferrer.createNullAwareGuard(receiverVariable);
+    NullAwareGuard nullAwareGuard = createNullAwareGuard(receiverVariable);
     Expression readReceiver = createVariableGet(receiverVariable);
     Expression writeReceiver = createVariableGet(receiverVariable);
     DartType nonNullReceiverType = receiverType.toNonNull();
@@ -5440,13 +5292,12 @@
       left = read;
     }
 
-    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget writeTarget = findInterfaceMember(
         nonNullReceiverType, node.propertyName, node.writeOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         includeExtensionMethods: true);
 
-    DartType valueType =
-        inferrer.getSetterType(writeTarget, nonNullReceiverType);
+    DartType valueType = getSetterType(writeTarget, nonNullReceiverType);
 
     ExpressionInferenceResult binaryResult = _computeBinaryExpression(
         node.binaryOffset,
@@ -5457,7 +5308,7 @@
         node.rhs,
         null);
 
-    binaryResult = inferrer.ensureAssignableResult(valueType, binaryResult,
+    binaryResult = ensureAssignableResult(valueType, binaryResult,
         fileOffset: node.fileOffset);
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
@@ -5530,7 +5381,7 @@
           createLet(writeVariable, createVariableGet(valueVariable)));
     }
 
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         resultType, action, nullAwareGuards.prepend(nullAwareGuard));
   }
 
@@ -5541,9 +5392,8 @@
             isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
-    DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType!);
-    DartType readIndexType =
-        inferrer.getIndexKeyType(readTarget, inferrer.thisType!);
+    DartType readType = getReturnType(readTarget, thisType!);
+    DartType readIndexType = getIndexKeyType(readTarget, thisType!);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -5559,18 +5409,15 @@
       writeIndex = createVariableGet(indexVariable);
     }
 
-    readIndex = inferrer.ensureAssignable(
-        readIndexType, indexResult.inferredType, readIndex);
+    readIndex =
+        ensureAssignable(readIndexType, indexResult.inferredType, readIndex);
 
     Expression read;
     if (readTarget.isMissing) {
-      read = inferrer.createMissingSuperIndexGet(node.readOffset, readIndex);
+      read = createMissingSuperIndexGet(node.readOffset, readIndex);
     } else {
       assert(readTarget.isInstanceMember || readTarget.isObjectMember);
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.readOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.readOffset, 'target',
           new InstrumentationValueForMember(node.getter!));
       read = new SuperMethodInvocation(
           indexGetName,
@@ -5597,11 +5444,9 @@
             isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
-    DartType writeIndexType =
-        inferrer.getIndexKeyType(writeTarget, inferrer.thisType!);
+    DartType writeIndexType = getIndexKeyType(writeTarget, thisType!);
 
-    DartType valueType =
-        inferrer.getIndexSetValueType(writeTarget, inferrer.thisType!);
+    DartType valueType = getIndexSetValueType(writeTarget, thisType!);
 
     ExpressionInferenceResult binaryResult = _computeBinaryExpression(
         node.binaryOffset,
@@ -5612,13 +5457,13 @@
         node.rhs,
         null);
 
-    binaryResult = inferrer.ensureAssignableResult(valueType, binaryResult,
+    binaryResult = ensureAssignableResult(valueType, binaryResult,
         fileOffset: node.fileOffset);
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
 
-    writeIndex = inferrer.ensureAssignable(
-        writeIndexType, indexResult.inferredType, writeIndex);
+    writeIndex =
+        ensureAssignable(writeIndexType, indexResult.inferredType, writeIndex);
 
     VariableDeclaration? valueVariable;
     Expression valueExpression;
@@ -5631,14 +5476,11 @@
 
     Expression write;
     if (writeTarget.isMissing) {
-      write = inferrer.createMissingSuperIndexSet(
+      write = createMissingSuperIndexSet(
           node.writeOffset, writeIndex, valueExpression);
     } else {
       assert(writeTarget.isInstanceMember || writeTarget.isObjectMember);
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.writeOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.writeOffset, 'target',
           new InstrumentationValueForMember(node.setter!));
       write = new SuperMethodInvocation(
           indexSetName,
@@ -5700,21 +5542,21 @@
         node.receiver, const UnknownType(), true,
         isVoidAllowed: false);
 
-    List<DartType> extensionTypeArguments =
-        inferrer.computeExtensionTypeArgument(node.extension,
-            node.explicitTypeArguments, receiverResult.inferredType);
+    List<DartType> extensionTypeArguments = computeExtensionTypeArgument(
+        node.extension,
+        node.explicitTypeArguments,
+        receiverResult.inferredType);
 
     ObjectAccessTarget readTarget = node.getter != null
         ? new ExtensionAccessTarget(
             node.getter!, null, ProcedureKind.Operator, extensionTypeArguments)
         : const ObjectAccessTarget.missing();
 
-    DartType receiverType = inferrer.getExtensionReceiverType(
-        node.extension, extensionTypeArguments);
+    DartType receiverType =
+        getExtensionReceiverType(node.extension, extensionTypeArguments);
 
-    Expression receiver = inferrer
-        .ensureAssignableResult(receiverType, receiverResult)
-        .expression;
+    Expression receiver =
+        ensureAssignableResult(receiverType, receiverResult).expression;
 
     VariableDeclaration? receiverVariable;
     Expression readReceiver;
@@ -5728,7 +5570,7 @@
       writeReceiver = createVariableGet(receiverVariable);
     }
 
-    DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
+    DartType readIndexType = getIndexKeyType(readTarget, receiverType);
 
     ExpressionInferenceResult indexResult =
         inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -5744,8 +5586,8 @@
       writeIndex = createVariableGet(indexVariable);
     }
 
-    readIndex = inferrer.ensureAssignable(
-        readIndexType, indexResult.inferredType, readIndex);
+    readIndex =
+        ensureAssignable(readIndexType, indexResult.inferredType, readIndex);
 
     ExpressionInferenceResult readResult = _computeIndexGet(
         node.readOffset,
@@ -5774,11 +5616,9 @@
             node.setter!, null, ProcedureKind.Operator, extensionTypeArguments)
         : const ObjectAccessTarget.missing();
 
-    DartType writeIndexType =
-        inferrer.getIndexKeyType(writeTarget, receiverType);
+    DartType writeIndexType = getIndexKeyType(writeTarget, receiverType);
 
-    DartType valueType =
-        inferrer.getIndexSetValueType(writeTarget, inferrer.thisType);
+    DartType valueType = getIndexSetValueType(writeTarget, thisType);
 
     ExpressionInferenceResult binaryResult = _computeBinaryExpression(
         node.binaryOffset,
@@ -5789,9 +5629,9 @@
         node.rhs,
         null);
 
-    writeIndex = inferrer.ensureAssignable(
-        writeIndexType, indexResult.inferredType, writeIndex);
-    binaryResult = inferrer.ensureAssignableResult(valueType, binaryResult,
+    writeIndex =
+        ensureAssignable(writeIndexType, indexResult.inferredType, writeIndex);
+    binaryResult = ensureAssignableResult(valueType, binaryResult,
         fileOffset: node.fileOffset);
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
@@ -5875,7 +5715,7 @@
   @override
   ExpressionInferenceResult visitNullLiteral(
       NullLiteral node, DartType typeContext) {
-    inferrer.flowAnalysis.nullLiteral(node);
+    flowAnalysis.nullLiteral(node);
     return new ExpressionInferenceResult(const NullType(), node);
   }
 
@@ -5904,25 +5744,21 @@
     Expression receiver = receiverResult.nullAwareAction;
     DartType receiverType = receiverResult.nullAwareActionType;
 
-    ObjectAccessTarget target = inferrer.findInterfaceMember(
+    ObjectAccessTarget target = findInterfaceMember(
         receiverType, node.name, node.fileOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         instrumented: true,
         includeExtensionMethods: true);
     if (target.isInstanceMember || target.isObjectMember) {
-      if (inferrer.instrumentation != null &&
-          receiverType == const DynamicType()) {
-        inferrer.instrumentation!.record(
-            inferrer.uriForInstrumentation,
-            node.fileOffset,
-            'target',
-            new InstrumentationValueForMember(target.member!));
+      if (instrumentation != null && receiverType == const DynamicType()) {
+        instrumentation!.record(uriForInstrumentation, node.fileOffset,
+            'target', new InstrumentationValueForMember(target.member!));
       }
     }
-    DartType writeContext = inferrer.getSetterType(target, receiverType);
+    DartType writeContext = getSetterType(target, receiverType);
     ExpressionInferenceResult rhsResult =
         inferExpression(node.value, writeContext, true, isVoidAllowed: true);
-    rhsResult = inferrer.ensureAssignableResult(writeContext, rhsResult,
+    rhsResult = ensureAssignableResult(writeContext, rhsResult,
         fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
     Expression rhs = rhsResult.expression;
     DartType rhsType = rhsResult.inferredType;
@@ -5931,7 +5767,7 @@
         node.fileOffset, receiver, receiverType, node.name, target, rhs,
         valueType: rhsType, forEffect: node.forEffect);
 
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         rhsType, replacement, nullAwareGuards);
   }
 
@@ -5949,8 +5785,7 @@
 
     VariableDeclaration receiverVariable =
         createVariable(receiver, receiverType);
-    NullAwareGuard nullAwareGuard =
-        inferrer.createNullAwareGuard(receiverVariable);
+    NullAwareGuard nullAwareGuard = createNullAwareGuard(receiverVariable);
     Expression readReceiver = createVariableGet(receiverVariable);
     Expression writeReceiver = createVariableGet(receiverVariable);
     DartType nonNullReceiverType = receiverType.toNonNull();
@@ -5961,7 +5796,7 @@
         .expressionInferenceResult;
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
+    flowAnalysis.ifNullExpression_rightBegin(read, readType);
 
     VariableDeclaration? readVariable;
     if (!node.forEffect) {
@@ -5969,29 +5804,27 @@
       read = createVariableGet(readVariable);
     }
 
-    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+    ObjectAccessTarget writeTarget = findInterfaceMember(
         nonNullReceiverType, node.name, node.writeOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         includeExtensionMethods: true);
 
-    DartType valueType =
-        inferrer.getSetterType(writeTarget, nonNullReceiverType);
+    DartType valueType = getSetterType(writeTarget, nonNullReceiverType);
 
     ExpressionInferenceResult valueResult =
         inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    valueResult = inferrer.ensureAssignableResult(valueType, valueResult);
+    valueResult = ensureAssignableResult(valueType, valueResult);
     Expression value = valueResult.expression;
 
     Expression write = _computePropertySet(node.writeOffset, writeReceiver,
         nonNullReceiverType, node.name, writeTarget, value,
         valueType: valueResult.inferredType, forEffect: node.forEffect);
 
-    inferrer.flowAnalysis.ifNullExpression_end();
+    flowAnalysis.ifNullExpression_end();
 
     DartType nonNullableReadType = readType.toNonNull();
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(nonNullableReadType, valueResult.inferredType,
-            inferrer.libraryBuilder.library);
+    DartType inferredType = typeSchemaEnvironment.getStandardUpperBound(
+        nonNullableReadType, valueResult.inferredType, libraryBuilder.library);
 
     Expression replacement;
     if (node.forEffect) {
@@ -6004,8 +5837,7 @@
       //           receiverVariable.name = value : null)
       //
 
-      Expression readEqualsNull =
-          inferrer.createEqualsNull(node.readOffset, read);
+      Expression readEqualsNull = createEqualsNull(node.readOffset, read);
       replacement = new ConditionalExpression(readEqualsNull, write,
           new NullLiteral()..fileOffset = node.writeOffset, inferredType)
         ..fileOffset = node.writeOffset;
@@ -6021,9 +5853,9 @@
       assert(readVariable != null);
 
       Expression readEqualsNull =
-          inferrer.createEqualsNull(receiverVariable.fileOffset, read);
+          createEqualsNull(receiverVariable.fileOffset, read);
       VariableGet variableGet = createVariableGet(readVariable!);
-      if (inferrer.libraryBuilder.isNonNullableByDefault &&
+      if (libraryBuilder.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
         variableGet.promotedType = nonNullableReadType;
       }
@@ -6033,7 +5865,7 @@
       replacement = createLet(readVariable, condition);
     }
 
-    return inferrer.createNullAwareExpressionInferenceResult(
+    return createNullAwareExpressionInferenceResult(
         inferredType, replacement, nullAwareGuards.prepend(nullAwareGuard));
   }
 
@@ -6052,35 +5884,35 @@
         isThisReceiver: node.receiver is ThisExpression);
     ExpressionInferenceResult readResult =
         propertyGetInferenceResult.expressionInferenceResult;
-    inferrer.flowAnalysis.propertyGet(node, node.receiver, node.name.text,
+    flowAnalysis.propertyGet(node, node.receiver, node.name.text,
         propertyGetInferenceResult.member, readResult.inferredType);
     ExpressionInferenceResult expressionInferenceResult =
-        inferrer.createNullAwareExpressionInferenceResult(
+        createNullAwareExpressionInferenceResult(
             readResult.inferredType, readResult.expression, nullAwareGuards);
-    inferrer.flowAnalysis
-        .forwardExpression(expressionInferenceResult.nullAwareAction, node);
+    flowAnalysis.forwardExpression(
+        expressionInferenceResult.nullAwareAction, node);
     return expressionInferenceResult;
   }
 
   @override
   InitializerInferenceResult visitRedirectingInitializer(
       RedirectingInitializer node) {
-    inferrer.inferConstructorParameterTypes(node.target);
+    inferConstructorParameterTypes(node.target);
     List<TypeParameter> classTypeParameters =
         node.target.enclosingClass.typeParameters;
     List<DartType> typeArguments = new List<DartType>.generate(
         classTypeParameters.length,
         (int i) => new TypeParameterType.withDefaultNullabilityForLibrary(
-            classTypeParameters[i], inferrer.libraryBuilder.library),
+            classTypeParameters[i], libraryBuilder.library),
         growable: false);
     ArgumentsImpl.setNonInferrableArgumentTypes(
         node.arguments as ArgumentsImpl, typeArguments);
     FunctionType functionType = replaceReturnType(
         node.target.function
-            .computeThisFunctionType(inferrer.libraryBuilder.nonNullable),
-        inferrer.coreTypes.thisInterfaceType(
-            node.target.enclosingClass, inferrer.libraryBuilder.nonNullable));
-    InvocationInferenceResult inferenceResult = inferrer.inferInvocation(
+            .computeThisFunctionType(libraryBuilder.nonNullable),
+        coreTypes.thisInterfaceType(
+            node.target.enclosingClass, libraryBuilder.nonNullable));
+    InvocationInferenceResult inferenceResult = inferInvocation(
         this,
         const UnknownType(),
         node.fileOffset,
@@ -6096,9 +5928,9 @@
 
   @override
   ExpressionInferenceResult visitRethrow(Rethrow node, DartType typeContext) {
-    inferrer.flowAnalysis.handleExit();
+    flowAnalysis.handleExit();
     return new ExpressionInferenceResult(
-        inferrer.isNonNullableByDefault
+        isNonNullableByDefault
             ? const NeverType.nonNullable()
             : const NeverType.legacy(),
         node);
@@ -6118,23 +5950,23 @@
     } else {
       inferredType = const NullType();
     }
-    closureContext.handleReturn(inferrer, node, inferredType, node.isArrow);
-    inferrer.flowAnalysis.handleExit();
+    closureContext.handleReturn(node, inferredType, node.isArrow);
+    flowAnalysis.handleExit();
     return const StatementInferenceResult();
   }
 
   @override
   ExpressionInferenceResult visitSetLiteral(
       SetLiteral node, DartType typeContext) {
-    Class setClass = inferrer.coreTypes.setClass;
-    InterfaceType setType = inferrer.coreTypes
-        .thisInterfaceType(setClass, inferrer.libraryBuilder.nonNullable);
+    Class setClass = coreTypes.setClass;
+    InterfaceType setType =
+        coreTypes.thisInterfaceType(setClass, libraryBuilder.nonNullable);
     List<DartType>? inferredTypes;
     DartType inferredTypeArgument;
     List<DartType>? formalTypes;
     List<DartType>? actualTypes;
     bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument;
-    bool typeChecksNeeded = !inferrer.isTopLevel;
+    bool typeChecksNeeded = !isTopLevel;
     Map<TreeNode, DartType>? inferredSpreadTypes;
     Map<Expression, DartType>? inferredConditionTypes;
     if (inferenceNeeded || typeChecksNeeded) {
@@ -6145,14 +5977,11 @@
     }
     TypeConstraintGatherer? gatherer;
     if (inferenceNeeded) {
-      gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
-          setType,
-          setClass.typeParameters,
-          typeContext,
-          inferrer.libraryBuilder.library,
+      gatherer = typeSchemaEnvironment.setupGenericTypeInference(
+          setType, setClass.typeParameters, typeContext, libraryBuilder.library,
           isConst: node.isConst);
-      inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
-          setClass.typeParameters, null, inferrer.libraryBuilder.library);
+      inferredTypes = typeSchemaEnvironment.partialInfer(
+          gatherer, setClass.typeParameters, null, libraryBuilder.library);
       inferredTypeArgument = inferredTypes[0];
     } else {
       inferredTypeArgument = node.typeArgument;
@@ -6175,18 +6004,15 @@
     }
     if (inferenceNeeded) {
       gatherer!.constrainArguments(formalTypes!, actualTypes!);
-      inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
-          gatherer,
-          setClass.typeParameters,
-          inferredTypes!,
-          inferrer.libraryBuilder.library);
-      if (inferrer.dataForTesting != null) {
-        inferrer.dataForTesting!.typeInferenceResult
-            .inferredTypeArguments[node] = inferredTypes;
+      inferredTypes = typeSchemaEnvironment.upwardsInfer(gatherer,
+          setClass.typeParameters, inferredTypes!, libraryBuilder.library);
+      if (dataForTesting != null) {
+        dataForTesting!.typeInferenceResult.inferredTypeArguments[node] =
+            inferredTypes;
       }
       inferredTypeArgument = inferredTypes[0];
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
+      instrumentation?.record(
+          uriForInstrumentation,
           node.fileOffset,
           'typeArgs',
           new InstrumentationValueForTypeArgs([inferredTypeArgument]));
@@ -6199,18 +6025,17 @@
       }
     }
     DartType inferredType = new InterfaceType(
-        setClass, inferrer.libraryBuilder.nonNullable, [inferredTypeArgument]);
-    if (!inferrer.isTopLevel) {
-      SourceLibraryBuilder library = inferrer.libraryBuilder;
+        setClass, libraryBuilder.nonNullable, [inferredTypeArgument]);
+    if (!isTopLevel) {
+      SourceLibraryBuilder library = libraryBuilder;
       if (inferenceNeeded) {
         if (!library.libraryFeatures.genericMetadata.isEnabled) {
-          inferrer.checkGenericFunctionTypeArgument(
-              node.typeArgument, node.fileOffset);
+          checkGenericFunctionTypeArgument(node.typeArgument, node.fileOffset);
         }
       }
 
       if (!library.loader.target.backendTarget.supportsSetLiterals) {
-        inferrer.helper.transformSetLiterals = true;
+        helper.transformSetLiterals = true;
       }
     }
     return new ExpressionInferenceResult(inferredType, node);
@@ -6224,7 +6049,7 @@
     TypeInferenceEngine.resolveInferenceNode(writeMember);
     ExpressionInferenceResult rhsResult =
         inferExpression(node.value, writeContext, true, isVoidAllowed: true);
-    rhsResult = inferrer.ensureAssignableResult(writeContext, rhsResult,
+    rhsResult = ensureAssignableResult(writeContext, rhsResult,
         fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
     Expression rhs = rhsResult.expression;
     node.value = rhs..parent = node;
@@ -6239,14 +6064,14 @@
     TypeInferenceEngine.resolveInferenceNode(target);
     DartType type = target.getterType;
 
-    if (!inferrer.isNonNullableByDefault) {
+    if (!isNonNullableByDefault) {
       type = legacyErasure(type);
     }
 
     if (target is Procedure && target.kind == ProcedureKind.Method) {
       Expression tearOff = new StaticTearOff(node.target as Procedure)
         ..fileOffset = node.fileOffset;
-      return inferrer.instantiateTearOff(type, typeContext, tearOff);
+      return instantiateTearOff(type, typeContext, tearOff);
     } else {
       return new ExpressionInferenceResult(type, node);
     }
@@ -6257,25 +6082,16 @@
       StaticInvocation node, DartType typeContext) {
     // ignore: unnecessary_null_comparison
     FunctionType calleeType = node.target != null
-        ? node.target.function
-            .computeFunctionType(inferrer.libraryBuilder.nonNullable)
-        : new FunctionType(
-            [], const DynamicType(), inferrer.libraryBuilder.nonNullable);
+        ? node.target.function.computeFunctionType(libraryBuilder.nonNullable)
+        : new FunctionType([], const DynamicType(), libraryBuilder.nonNullable);
     TypeArgumentsInfo typeArgumentsInfo = getTypeArgumentsInfo(node.arguments);
-    InvocationInferenceResult result = inferrer.inferInvocation(
-        this,
-        typeContext,
-        node.fileOffset,
-        calleeType,
-        node.arguments as ArgumentsImpl,
+    InvocationInferenceResult result = inferInvocation(this, typeContext,
+        node.fileOffset, calleeType, node.arguments as ArgumentsImpl,
         staticTarget: node.target);
     // ignore: unnecessary_null_comparison
-    if (!inferrer.isTopLevel && node.target != null) {
-      inferrer.libraryBuilder.checkBoundsInStaticInvocation(
-          node,
-          inferrer.typeSchemaEnvironment,
-          inferrer.helper.uri,
-          typeArgumentsInfo);
+    if (!isTopLevel && node.target != null) {
+      libraryBuilder.checkBoundsInStaticInvocation(
+          node, typeSchemaEnvironment, helper.uri, typeArgumentsInfo);
     }
     return new ExpressionInferenceResult(
         result.inferredType, result.applyResult(node));
@@ -6284,39 +6100,37 @@
   @override
   ExpressionInferenceResult visitStringConcatenation(
       StringConcatenation node, DartType typeContext) {
-    if (!inferrer.isTopLevel) {
+    if (!isTopLevel) {
       for (int index = 0; index < node.expressions.length; index++) {
         ExpressionInferenceResult result = inferExpression(
-            node.expressions[index], const UnknownType(), !inferrer.isTopLevel,
+            node.expressions[index], const UnknownType(), !isTopLevel,
             isVoidAllowed: false);
         node.expressions[index] = result.expression..parent = node;
       }
     }
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.stringRawType(inferrer.libraryBuilder.nonNullable),
-        node);
+        coreTypes.stringRawType(libraryBuilder.nonNullable), node);
   }
 
   @override
   ExpressionInferenceResult visitStringLiteral(
       StringLiteral node, DartType typeContext) {
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.stringRawType(inferrer.libraryBuilder.nonNullable),
-        node);
+        coreTypes.stringRawType(libraryBuilder.nonNullable), node);
   }
 
   @override
   InitializerInferenceResult visitSuperInitializer(SuperInitializer node) {
-    inferrer.inferConstructorParameterTypes(node.target);
+    inferConstructorParameterTypes(node.target);
     Substitution substitution = Substitution.fromSupertype(
-        inferrer.classHierarchy.getClassAsInstanceOf(
-            inferrer.thisType!.classNode, node.target.enclosingClass)!);
+        classHierarchy.getClassAsInstanceOf(
+            thisType!.classNode, node.target.enclosingClass)!);
     FunctionType functionType = replaceReturnType(
         substitution.substituteType(node.target.function
-            .computeThisFunctionType(inferrer.libraryBuilder.nonNullable)
+            .computeThisFunctionType(libraryBuilder.nonNullable)
             .withoutTypeParameters) as FunctionType,
-        inferrer.thisType!);
-    InvocationInferenceResult inferenceResult = inferrer.inferInvocation(
+        thisType!);
+    InvocationInferenceResult inferenceResult = inferInvocation(
         this,
         const UnknownType(),
         node.fileOffset,
@@ -6332,14 +6146,11 @@
   ExpressionInferenceResult visitAbstractSuperMethodInvocation(
       AbstractSuperMethodInvocation node, DartType typeContext) {
     if (node.interfaceTarget != null) {
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.fileOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.fileOffset, 'target',
           new InstrumentationValueForMember(node.interfaceTarget!));
     }
     assert(node.interfaceTarget == null || node.interfaceTarget is Procedure);
-    return inferrer.inferSuperMethodInvocation(this, node, node.name,
+    return inferSuperMethodInvocation(this, node, node.name,
         node.arguments as ArgumentsImpl, typeContext, node.interfaceTarget);
   }
 
@@ -6347,14 +6158,11 @@
   ExpressionInferenceResult visitSuperMethodInvocation(
       SuperMethodInvocation node, DartType typeContext) {
     if (node.interfaceTarget != null) {
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.fileOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.fileOffset, 'target',
           new InstrumentationValueForMember(node.interfaceTarget!));
     }
     assert(node.interfaceTarget == null || node.interfaceTarget is Procedure);
-    return inferrer.inferSuperMethodInvocation(this, node, node.name,
+    return inferSuperMethodInvocation(this, node, node.name,
         node.arguments as ArgumentsImpl, typeContext, node.interfaceTarget);
   }
 
@@ -6362,13 +6170,10 @@
   ExpressionInferenceResult visitAbstractSuperPropertyGet(
       AbstractSuperPropertyGet node, DartType typeContext) {
     if (node.interfaceTarget != null) {
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.fileOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.fileOffset, 'target',
           new InstrumentationValueForMember(node.interfaceTarget!));
     }
-    return inferrer.inferSuperPropertyGet(
+    return inferSuperPropertyGet(
         node, node.name, typeContext, node.interfaceTarget);
   }
 
@@ -6376,36 +6181,31 @@
   ExpressionInferenceResult visitSuperPropertyGet(
       SuperPropertyGet node, DartType typeContext) {
     if (node.interfaceTarget != null) {
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.fileOffset,
-          'target',
+      instrumentation?.record(uriForInstrumentation, node.fileOffset, 'target',
           new InstrumentationValueForMember(node.interfaceTarget!));
     }
-    return inferrer.inferSuperPropertyGet(
+    return inferSuperPropertyGet(
         node, node.name, typeContext, node.interfaceTarget);
   }
 
   @override
   ExpressionInferenceResult visitAbstractSuperPropertySet(
       AbstractSuperPropertySet node, DartType typeContext) {
-    DartType receiverType = inferrer.classHierarchy.getTypeAsInstanceOf(
-        inferrer.thisType!,
-        inferrer.thisType!.classNode.supertype!.classNode,
-        inferrer.libraryBuilder.library)!;
+    DartType receiverType = classHierarchy.getTypeAsInstanceOf(thisType!,
+        thisType!.classNode.supertype!.classNode, libraryBuilder.library)!;
 
     ObjectAccessTarget writeTarget = node.interfaceTarget != null
         ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget!,
             isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
-    DartType writeContext = inferrer.getSetterType(writeTarget, receiverType);
+    DartType writeContext = getSetterType(writeTarget, receiverType);
     if (node.interfaceTarget != null) {
-      writeContext = inferrer.computeTypeFromSuperClass(
+      writeContext = computeTypeFromSuperClass(
           node.interfaceTarget!.enclosingClass!, writeContext);
     }
     ExpressionInferenceResult rhsResult =
         inferExpression(node.value, writeContext, true, isVoidAllowed: true);
-    rhsResult = inferrer.ensureAssignableResult(writeContext, rhsResult,
+    rhsResult = ensureAssignableResult(writeContext, rhsResult,
         fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
     Expression rhs = rhsResult.expression;
     node.value = rhs..parent = node;
@@ -6415,23 +6215,21 @@
   @override
   ExpressionInferenceResult visitSuperPropertySet(
       SuperPropertySet node, DartType typeContext) {
-    DartType receiverType = inferrer.classHierarchy.getTypeAsInstanceOf(
-        inferrer.thisType!,
-        inferrer.thisType!.classNode.supertype!.classNode,
-        inferrer.libraryBuilder.library)!;
+    DartType receiverType = classHierarchy.getTypeAsInstanceOf(thisType!,
+        thisType!.classNode.supertype!.classNode, libraryBuilder.library)!;
 
     ObjectAccessTarget writeTarget = node.interfaceTarget != null
         ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget!,
             isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
-    DartType writeContext = inferrer.getSetterType(writeTarget, receiverType);
+    DartType writeContext = getSetterType(writeTarget, receiverType);
     if (node.interfaceTarget != null) {
-      writeContext = inferrer.computeTypeFromSuperClass(
+      writeContext = computeTypeFromSuperClass(
           node.interfaceTarget!.enclosingClass!, writeContext);
     }
     ExpressionInferenceResult rhsResult =
         inferExpression(node.value, writeContext, true, isVoidAllowed: true);
-    rhsResult = inferrer.ensureAssignableResult(writeContext, rhsResult,
+    rhsResult = ensureAssignableResult(writeContext, rhsResult,
         fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
     Expression rhs = rhsResult.expression;
     node.value = rhs..parent = node;
@@ -6457,15 +6255,14 @@
       }
     }
 
-    inferrer.flowAnalysis.switchStatement_expressionEnd(node);
+    flowAnalysis.switchStatement_expressionEnd(node);
 
     bool hasDefault = false;
     bool lastCaseTerminates = true;
     for (int caseIndex = 0; caseIndex < node.cases.length; ++caseIndex) {
       SwitchCaseImpl switchCase = node.cases[caseIndex] as SwitchCaseImpl;
       hasDefault = hasDefault || switchCase.isDefault;
-      inferrer.flowAnalysis
-          .switchStatement_beginCase(switchCase.hasLabel, node);
+      flowAnalysis.switchStatement_beginCase(switchCase.hasLabel, node);
       for (int index = 0; index < switchCase.expressions.length; index++) {
         ExpressionInferenceResult caseExpressionResult = inferExpression(
             switchCase.expressions[index], expressionType, true,
@@ -6481,20 +6278,20 @@
           }
         }
 
-        if (!inferrer.isTopLevel) {
-          if (inferrer.libraryBuilder.isNonNullableByDefault) {
-            if (!inferrer.typeSchemaEnvironment.isSubtypeOf(caseExpressionType,
+        if (!isTopLevel) {
+          if (libraryBuilder.isNonNullableByDefault) {
+            if (!typeSchemaEnvironment.isSubtypeOf(caseExpressionType,
                 expressionType, SubtypeCheckMode.withNullabilities)) {
-              inferrer.helper.addProblem(
+              helper.addProblem(
                   templateSwitchExpressionNotSubtype.withArguments(
                       caseExpressionType,
                       expressionType,
-                      inferrer.isNonNullableByDefault),
+                      isNonNullableByDefault),
                   caseExpression.fileOffset,
                   noLength,
                   context: [
                     messageSwitchExpressionNotAssignableCause.withLocation(
-                        inferrer.uriForInstrumentation,
+                        uriForInstrumentation,
                         node.expression.fileOffset,
                         noLength)
                   ]);
@@ -6502,17 +6299,17 @@
           } else {
             // Check whether the expression type is assignable to the case
             // expression type.
-            if (!inferrer.isAssignable(expressionType, caseExpressionType)) {
-              inferrer.helper.addProblem(
+            if (!isAssignable(expressionType, caseExpressionType)) {
+              helper.addProblem(
                   templateSwitchExpressionNotAssignable.withArguments(
                       expressionType,
                       caseExpressionType,
-                      inferrer.isNonNullableByDefault),
+                      isNonNullableByDefault),
                   caseExpression.fileOffset,
                   noLength,
                   context: [
                     messageSwitchExpressionNotAssignableCause.withLocation(
-                        inferrer.uriForInstrumentation,
+                        uriForInstrumentation,
                         node.expression.fileOffset,
                         noLength)
                   ]);
@@ -6525,25 +6322,22 @@
         switchCase.body = bodyResult.statement..parent = switchCase;
       }
 
-      if (inferrer.isNonNullableByDefault) {
-        lastCaseTerminates = !inferrer.flowAnalysis.isReachable;
-        if (!inferrer.isTopLevel) {
+      if (isNonNullableByDefault) {
+        lastCaseTerminates = !flowAnalysis.isReachable;
+        if (!isTopLevel) {
           // The last case block is allowed to complete normally.
-          if (caseIndex < node.cases.length - 1 &&
-              inferrer.flowAnalysis.isReachable) {
-            inferrer.libraryBuilder.addProblem(messageSwitchCaseFallThrough,
-                switchCase.fileOffset, noLength, inferrer.helper.uri);
+          if (caseIndex < node.cases.length - 1 && flowAnalysis.isReachable) {
+            libraryBuilder.addProblem(messageSwitchCaseFallThrough,
+                switchCase.fileOffset, noLength, helper.uri);
           }
         }
       }
     }
     node.isExplicitlyExhaustive = enumFields != null && enumFields.isEmpty;
     bool isExhaustive = node.isExplicitlyExhaustive || hasDefault;
-    inferrer.flowAnalysis.switchStatement_end(isExhaustive);
+    flowAnalysis.switchStatement_end(isExhaustive);
     Statement? replacement;
-    if (isExhaustive &&
-        !hasDefault &&
-        inferrer.shouldThrowUnsoundnessException) {
+    if (isExhaustive && !hasDefault && shouldThrowUnsoundnessException) {
       if (!lastCaseTerminates) {
         LabeledStatement breakTarget;
         if (node.parent is LabeledStatement) {
@@ -6564,7 +6358,7 @@
       node.cases.add(new SwitchCase(
           [],
           [],
-          _createExpressionStatement(inferrer.createReachabilityError(
+          _createExpressionStatement(createReachabilityError(
               node.fileOffset,
               messageNeverReachableSwitchDefaultError,
               messageNeverReachableSwitchDefaultWarning)),
@@ -6580,32 +6374,30 @@
   @override
   ExpressionInferenceResult visitSymbolLiteral(
       SymbolLiteral node, DartType typeContext) {
-    DartType inferredType =
-        inferrer.coreTypes.symbolRawType(inferrer.libraryBuilder.nonNullable);
+    DartType inferredType = coreTypes.symbolRawType(libraryBuilder.nonNullable);
     return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
   ExpressionInferenceResult visitThisExpression(
       ThisExpression node, DartType typeContext) {
-    inferrer.flowAnalysis.thisOrSuper(node, inferrer.thisType!);
-    return new ExpressionInferenceResult(inferrer.thisType!, node);
+    flowAnalysis.thisOrSuper(node, thisType!);
+    return new ExpressionInferenceResult(thisType!, node);
   }
 
   @override
   ExpressionInferenceResult visitThrow(Throw node, DartType typeContext) {
     ExpressionInferenceResult expressionResult = inferExpression(
-        node.expression, const UnknownType(), !inferrer.isTopLevel,
+        node.expression, const UnknownType(), !isTopLevel,
         isVoidAllowed: false);
     node.expression = expressionResult.expression..parent = node;
-    inferrer.flowAnalysis.handleExit();
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-      if (!inferrer.isAssignable(
-          inferrer.typeSchemaEnvironment.objectNonNullableRawType,
+    flowAnalysis.handleExit();
+    if (!isTopLevel && isNonNullableByDefault) {
+      if (!isAssignable(typeSchemaEnvironment.objectNonNullableRawType,
           expressionResult.inferredType)) {
         return new ExpressionInferenceResult(
             const DynamicType(),
-            inferrer.helper.buildProblem(
+            helper.buildProblem(
                 templateThrowingNotAssignableToObjectError.withArguments(
                     expressionResult.inferredType, true),
                 node.expression.fileOffset,
@@ -6614,7 +6406,7 @@
     }
     // Return BottomType in legacy mode for compatibility.
     return new ExpressionInferenceResult(
-        inferrer.isNonNullableByDefault
+        isNonNullableByDefault
             ? const NeverType.nonNullable()
             : const NullType(),
         node);
@@ -6629,24 +6421,24 @@
 
   StatementInferenceResult visitTryStatement(TryStatement node) {
     if (node.finallyBlock != null) {
-      inferrer.flowAnalysis.tryFinallyStatement_bodyBegin();
+      flowAnalysis.tryFinallyStatement_bodyBegin();
     }
     Statement tryBodyWithAssignedInfo = node.tryBlock;
     if (node.catchBlocks.isNotEmpty) {
-      inferrer.flowAnalysis.tryCatchStatement_bodyBegin();
+      flowAnalysis.tryCatchStatement_bodyBegin();
     }
 
     StatementInferenceResult tryBlockResult = inferStatement(node.tryBlock);
 
     if (node.catchBlocks.isNotEmpty) {
-      inferrer.flowAnalysis.tryCatchStatement_bodyEnd(tryBodyWithAssignedInfo);
+      flowAnalysis.tryCatchStatement_bodyEnd(tryBodyWithAssignedInfo);
       for (Catch catchBlock in node.catchBlocks) {
-        inferrer.flowAnalysis.tryCatchStatement_catchBegin(
+        flowAnalysis.tryCatchStatement_catchBegin(
             catchBlock.exception, catchBlock.stackTrace);
         visitCatch(catchBlock);
-        inferrer.flowAnalysis.tryCatchStatement_catchEnd();
+        flowAnalysis.tryCatchStatement_catchEnd();
       }
-      inferrer.flowAnalysis.tryCatchStatement_end();
+      flowAnalysis.tryCatchStatement_end();
     }
 
     StatementInferenceResult? finalizerResult;
@@ -6654,10 +6446,10 @@
       // If a try statement has no catch blocks, the finally block uses the
       // assigned variables from the try block in [tryBodyWithAssignedInfo],
       // otherwise it uses the assigned variables for the
-      inferrer.flowAnalysis.tryFinallyStatement_finallyBegin(
+      flowAnalysis.tryFinallyStatement_finallyBegin(
           node.catchBlocks.isNotEmpty ? node : tryBodyWithAssignedInfo);
       finalizerResult = inferStatement(node.finallyBlock!);
-      inferrer.flowAnalysis.tryFinallyStatement_end();
+      flowAnalysis.tryFinallyStatement_end();
     }
     Statement result =
         tryBlockResult.hasChanged ? tryBlockResult.statement : node.tryBlock;
@@ -6673,15 +6465,14 @@
               : node.finallyBlock!)
         ..fileOffset = node.fileOffset;
     }
-    inferrer.libraryBuilder.loader.dataForTesting?.registerAlias(node, result);
+    libraryBuilder.loader.dataForTesting?.registerAlias(node, result);
     return new StatementInferenceResult.single(result);
   }
 
   @override
   ExpressionInferenceResult visitTypeLiteral(
       TypeLiteral node, DartType typeContext) {
-    DartType inferredType =
-        inferrer.coreTypes.typeRawType(inferrer.libraryBuilder.nonNullable);
+    DartType inferredType = coreTypes.typeRawType(libraryBuilder.nonNullable);
     return new ExpressionInferenceResult(inferredType, node);
   }
 
@@ -6691,25 +6482,24 @@
     VariableDeclarationImpl variable = node.variable as VariableDeclarationImpl;
     bool isDefinitelyAssigned = false;
     bool isDefinitelyUnassigned = false;
-    if (inferrer.isNonNullableByDefault) {
-      isDefinitelyAssigned = inferrer.flowAnalysis.isAssigned(variable);
-      isDefinitelyUnassigned = inferrer.flowAnalysis.isUnassigned(variable);
+    if (isNonNullableByDefault) {
+      isDefinitelyAssigned = flowAnalysis.isAssigned(variable);
+      isDefinitelyUnassigned = flowAnalysis.isUnassigned(variable);
     }
     DartType declaredOrInferredType = variable.lateType ?? variable.type;
     DartType? promotedType;
-    if (inferrer.isNonNullableByDefault) {
-      promotedType = inferrer.flowAnalysis.promotedType(variable);
+    if (isNonNullableByDefault) {
+      promotedType = flowAnalysis.promotedType(variable);
     }
     ExpressionInferenceResult rhsResult = inferExpression(
         node.value, promotedType ?? declaredOrInferredType, true,
         isVoidAllowed: true);
-    rhsResult = inferrer.ensureAssignableResult(
-        declaredOrInferredType, rhsResult,
+    rhsResult = ensureAssignableResult(declaredOrInferredType, rhsResult,
         fileOffset: node.fileOffset,
         isVoidAllowed: declaredOrInferredType is VoidType);
     Expression rhs = rhsResult.expression;
-    inferrer.flowAnalysis
-        .write(node, variable, rhsResult.inferredType, rhsResult.expression);
+    flowAnalysis.write(
+        node, variable, rhsResult.inferredType, rhsResult.expression);
     DartType resultType = rhsResult.inferredType;
     Expression resultExpression;
     if (variable.lateSetter != null) {
@@ -6720,12 +6510,12 @@
       // Future calls to flow analysis will be using `resultExpression` to refer
       // to the variable set, so instruct flow analysis to forward the
       // expression information.
-      inferrer.flowAnalysis.forwardExpression(resultExpression, node);
+      flowAnalysis.forwardExpression(resultExpression, node);
     } else {
       node.value = rhs..parent = node;
       resultExpression = node;
     }
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
+    if (!isTopLevel && isNonNullableByDefault) {
       // Synthetic variables, local functions, and variables with
       // invalid types aren't checked.
       if (variable.name != null &&
@@ -6736,7 +6526,7 @@
           if (isDefinitelyAssigned) {
             return new ExpressionInferenceResult(
                 resultType,
-                inferrer.helper.wrapInProblem(
+                helper.wrapInProblem(
                     resultExpression,
                     templateLateDefinitelyAssignedError
                         .withArguments(node.variable.name!),
@@ -6747,7 +6537,7 @@
           if (!isDefinitelyUnassigned) {
             return new ExpressionInferenceResult(
                 resultType,
-                inferrer.helper.wrapInProblem(
+                helper.wrapInProblem(
                     resultExpression,
                     templateFinalPossiblyAssignedError
                         .withArguments(node.variable.name!),
@@ -6767,32 +6557,28 @@
         node.isImplicitlyTyped ? const UnknownType() : node.type;
     DartType inferredType;
     ExpressionInferenceResult? initializerResult;
-    inferrer.flowAnalysis.declare(node, node.hasDeclaredInitializer);
+    flowAnalysis.declare(node, node.hasDeclaredInitializer);
     if (node.initializer != null) {
       if (node.isLate && node.hasDeclaredInitializer) {
-        inferrer.flowAnalysis.lateInitializer_begin(node);
+        flowAnalysis.lateInitializer_begin(node);
       }
       initializerResult = inferExpression(node.initializer!, declaredType,
-          !inferrer.isTopLevel || node.isImplicitlyTyped,
+          !isTopLevel || node.isImplicitlyTyped,
           isVoidAllowed: true);
       if (node.isLate && node.hasDeclaredInitializer) {
-        inferrer.flowAnalysis.lateInitializer_end();
+        flowAnalysis.lateInitializer_end();
       }
-      inferredType = inferrer.inferDeclarationType(
-          initializerResult.inferredType,
+      inferredType = inferDeclarationType(initializerResult.inferredType,
           forSyntheticVariable: node.name == null);
     } else {
       inferredType = const DynamicType();
     }
     if (node.isImplicitlyTyped) {
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.fileOffset,
-          'type',
+      instrumentation?.record(uriForInstrumentation, node.fileOffset, 'type',
           new InstrumentationValueForType(inferredType));
-      if (inferrer.dataForTesting != null) {
-        inferrer.dataForTesting!.typeInferenceResult
-            .inferredVariableTypes[node] = inferredType;
+      if (dataForTesting != null) {
+        dataForTesting!.typeInferenceResult.inferredVariableTypes[node] =
+            inferredType;
       }
       node.type = inferredType;
     }
@@ -6802,39 +6588,36 @@
       // level inference.  Figure out how to prevent this.
       // ignore: unnecessary_null_comparison
       if (initializerType != null) {
-        inferrer.flowAnalysis.initialize(
+        flowAnalysis.initialize(
             node, initializerType, initializerResult.expression,
             isFinal: node.isFinal,
             isLate: node.isLate,
             isImplicitlyTyped: node.isImplicitlyTyped);
       }
-      initializerResult = inferrer.ensureAssignableResult(
-          node.type, initializerResult,
+      initializerResult = ensureAssignableResult(node.type, initializerResult,
           fileOffset: node.fileOffset, isVoidAllowed: node.type is VoidType);
       Expression initializer = initializerResult.expression;
       node.initializer = initializer..parent = node;
     }
     if (node.isLate &&
-        inferrer.libraryBuilder.loader.target.backendTarget
-            .isLateLocalLoweringEnabled(
-                hasInitializer: node.hasDeclaredInitializer,
-                isFinal: node.isFinal,
-                isPotentiallyNullable: node.type.isPotentiallyNullable)) {
+        libraryBuilder.loader.target.backendTarget.isLateLocalLoweringEnabled(
+            hasInitializer: node.hasDeclaredInitializer,
+            isFinal: node.isFinal,
+            isPotentiallyNullable: node.type.isPotentiallyNullable)) {
       int fileOffset = node.fileOffset;
 
       List<Statement> result = <Statement>[];
       result.add(node);
 
       late_lowering.IsSetEncoding isSetEncoding =
-          late_lowering.computeIsSetEncoding(node.type,
-              late_lowering.computeIsSetStrategy(inferrer.libraryBuilder));
+          late_lowering.computeIsSetEncoding(
+              node.type, late_lowering.computeIsSetStrategy(libraryBuilder));
       VariableDeclaration? isSetVariable;
       if (isSetEncoding == late_lowering.IsSetEncoding.useIsSetField) {
         isSetVariable = new VariableDeclaration(
             late_lowering.computeLateLocalIsSetName(node.name!),
             initializer: new BoolLiteral(false)..fileOffset = fileOffset,
-            type: inferrer.coreTypes
-                .boolRawType(inferrer.libraryBuilder.nonNullable),
+            type: coreTypes.boolRawType(libraryBuilder.nonNullable),
             isLowered: true)
           ..fileOffset = fileOffset;
         result.add(isSetVariable);
@@ -6864,14 +6647,14 @@
           new FunctionNode(
               node.initializer == null
                   ? late_lowering.createGetterBodyWithoutInitializer(
-                      inferrer.coreTypes, fileOffset, node.name!, node.type,
+                      coreTypes, fileOffset, node.name!, node.type,
                       createVariableRead: createVariableRead,
                       createIsSetRead: createIsSetRead,
                       isSetEncoding: isSetEncoding,
                       forField: false)
                   : (node.isFinal
                       ? late_lowering.createGetterWithInitializerWithRecheck(
-                          inferrer.coreTypes,
+                          coreTypes,
                           fileOffset,
                           node.name!,
                           node.type,
@@ -6882,12 +6665,8 @@
                           createIsSetWrite: createIsSetWrite,
                           isSetEncoding: isSetEncoding,
                           forField: false)
-                      : late_lowering.createGetterWithInitializer(
-                          inferrer.coreTypes,
-                          fileOffset,
-                          node.name!,
-                          node.type,
-                          node.initializer!,
+                      : late_lowering.createGetterWithInitializer(coreTypes,
+                          fileOffset, node.name!, node.type, node.initializer!,
                           createVariableRead: createVariableRead,
                           createVariableWrite: createVariableWrite,
                           createIsSetRead: createIsSetRead,
@@ -6895,8 +6674,8 @@
                           isSetEncoding: isSetEncoding)),
               returnType: node.type))
         ..fileOffset = fileOffset;
-      getVariable.type = getter.function
-          .computeFunctionType(inferrer.libraryBuilder.nonNullable);
+      getVariable.type =
+          getter.function.computeFunctionType(libraryBuilder.nonNullable);
       node.lateGetter = getVariable;
       result.add(getter);
 
@@ -6914,12 +6693,8 @@
                 setVariable,
                 new FunctionNode(
                     node.isFinal
-                        ? late_lowering.createSetterBodyFinal(
-                            inferrer.coreTypes,
-                            fileOffset,
-                            node.name!,
-                            setterParameter,
-                            node.type,
+                        ? late_lowering.createSetterBodyFinal(coreTypes,
+                            fileOffset, node.name!, setterParameter, node.type,
                             shouldReturnValue: true,
                             createVariableRead: createVariableRead,
                             createVariableWrite: createVariableWrite,
@@ -6927,8 +6702,8 @@
                             createIsSetWrite: createIsSetWrite,
                             isSetEncoding: isSetEncoding,
                             forField: false)
-                        : late_lowering.createSetterBody(inferrer.coreTypes,
-                            fileOffset, node.name!, setterParameter, node.type,
+                        : late_lowering.createSetterBody(coreTypes, fileOffset,
+                            node.name!, setterParameter, node.type,
                             shouldReturnValue: true,
                             createVariableWrite: createVariableWrite,
                             createIsSetWrite: createIsSetWrite,
@@ -6940,23 +6715,22 @@
             // TODO(johnniwinther): Reinsert the file offset when the vm doesn't
             //  use it for function declaration identity.
             /*..fileOffset = fileOffset*/;
-        setVariable.type = setter.function
-            .computeFunctionType(inferrer.libraryBuilder.nonNullable);
+        setVariable.type =
+            setter.function.computeFunctionType(libraryBuilder.nonNullable);
         node.lateSetter = setVariable;
         result.add(setter);
       }
       node.isLate = false;
       node.lateType = node.type;
       if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
-        node.initializer = new StaticInvocation(
-            inferrer.coreTypes.createSentinelMethod,
+        node.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
             new Arguments([], types: [node.type])..fileOffset = fileOffset)
           ..fileOffset = fileOffset
           ..parent = node;
       } else {
         node.initializer = null;
       }
-      node.type = inferrer.computeNullable(node.type);
+      node.type = computeNullable(node.type);
       node.lateName = node.name;
       node.isLowered = true;
       node.name = late_lowering.computeLateLocalName(node.name!);
@@ -6973,28 +6747,25 @@
     DartType? promotedType;
     DartType declaredOrInferredType = variable.lateType ?? variable.type;
     if (isExtensionThis(variable)) {
-      inferrer.flowAnalysis.thisOrSuper(node, variable.type);
-    } else if (inferrer.isNonNullableByDefault && node.forNullGuardedAccess) {
+      flowAnalysis.thisOrSuper(node, variable.type);
+    } else if (isNonNullableByDefault && node.forNullGuardedAccess) {
       DartType nonNullableType = variable.type.toNonNull();
       if (nonNullableType != variable.type) {
         promotedType = nonNullableType;
       }
     } else if (!variable.isLocalFunction) {
       // Don't promote local functions.
-      promotedType = inferrer.flowAnalysis.variableRead(node, variable);
+      promotedType = flowAnalysis.variableRead(node, variable);
     }
     if (promotedType != null) {
-      inferrer.instrumentation?.record(
-          inferrer.uriForInstrumentation,
-          node.fileOffset,
-          'promotedType',
-          new InstrumentationValueForType(promotedType));
+      instrumentation?.record(uriForInstrumentation, node.fileOffset,
+          'promotedType', new InstrumentationValueForType(promotedType));
     }
     node.promotedType = promotedType;
     DartType resultType = promotedType ?? declaredOrInferredType;
     Expression resultExpression;
     if (variable.isLocalFunction) {
-      return inferrer.instantiateTearOff(resultType, typeContext, node);
+      return instantiateTearOff(resultType, typeContext, node);
     } else if (variable.lateGetter != null) {
       resultExpression = new LocalFunctionInvocation(variable.lateGetter!,
           new Arguments(<Expression>[])..fileOffset = node.fileOffset,
@@ -7003,23 +6774,20 @@
       // Future calls to flow analysis will be using `resultExpression` to refer
       // to the variable get, so instruct flow analysis to forward the
       // expression information.
-      inferrer.flowAnalysis.forwardExpression(resultExpression, node);
+      flowAnalysis.forwardExpression(resultExpression, node);
     } else {
       resultExpression = node;
     }
-    if (!inferrer.isTopLevel) {
-      bool isUnassigned = !inferrer.flowAnalysis.isAssigned(variable);
+    if (!isTopLevel) {
+      bool isUnassigned = !flowAnalysis.isAssigned(variable);
       if (isUnassigned) {
-        inferrer.dataForTesting?.flowAnalysisResult.potentiallyUnassignedNodes
-            .add(node);
+        dataForTesting?.flowAnalysisResult.potentiallyUnassignedNodes.add(node);
       }
-      bool isDefinitelyUnassigned =
-          inferrer.flowAnalysis.isUnassigned(variable);
+      bool isDefinitelyUnassigned = flowAnalysis.isUnassigned(variable);
       if (isDefinitelyUnassigned) {
-        inferrer.dataForTesting?.flowAnalysisResult.definitelyUnassignedNodes
-            .add(node);
+        dataForTesting?.flowAnalysisResult.definitelyUnassignedNodes.add(node);
       }
-      if (inferrer.isNonNullableByDefault) {
+      if (isNonNullableByDefault) {
         // Synthetic variables, local functions, and variables with
         // invalid types aren't checked.
         if (variable.name != null &&
@@ -7030,7 +6798,7 @@
               String name = variable.lateName ?? variable.name!;
               return new ExpressionInferenceResult(
                   resultType,
-                  inferrer.helper.wrapInProblem(
+                  helper.wrapInProblem(
                       resultExpression,
                       templateLateDefinitelyUnassignedError.withArguments(name),
                       node.fileOffset,
@@ -7041,7 +6809,7 @@
               if (variable.isFinal) {
                 return new ExpressionInferenceResult(
                     resultType,
-                    inferrer.helper.wrapInProblem(
+                    helper.wrapInProblem(
                         resultExpression,
                         templateFinalNotAssignedError
                             .withArguments(node.variable.name!),
@@ -7050,7 +6818,7 @@
               } else if (declaredOrInferredType.isPotentiallyNonNullable) {
                 return new ExpressionInferenceResult(
                     resultType,
-                    inferrer.helper.wrapInProblem(
+                    helper.wrapInProblem(
                         resultExpression,
                         templateNonNullableNotAssignedError
                             .withArguments(node.variable.name!),
@@ -7067,22 +6835,21 @@
 
   @override
   StatementInferenceResult visitWhileStatement(WhileStatement node) {
-    inferrer.flowAnalysis.whileStatement_conditionBegin(node);
+    flowAnalysis.whileStatement_conditionBegin(node);
     InterfaceType expectedType =
-        inferrer.coreTypes.boolRawType(inferrer.libraryBuilder.nonNullable);
+        coreTypes.boolRawType(libraryBuilder.nonNullable);
     ExpressionInferenceResult conditionResult = inferExpression(
-        node.condition, expectedType, !inferrer.isTopLevel,
+        node.condition, expectedType, !isTopLevel,
         isVoidAllowed: false);
-    Expression condition = inferrer
-        .ensureAssignableResult(expectedType, conditionResult)
-        .expression;
+    Expression condition =
+        ensureAssignableResult(expectedType, conditionResult).expression;
     node.condition = condition..parent = node;
-    inferrer.flowAnalysis.whileStatement_bodyBegin(node, node.condition);
+    flowAnalysis.whileStatement_bodyBegin(node, node.condition);
     StatementInferenceResult bodyResult = inferStatement(node.body);
     if (bodyResult.hasChanged) {
       node.body = bodyResult.statement..parent = node;
     }
-    inferrer.flowAnalysis.whileStatement_end();
+    flowAnalysis.whileStatement_end();
     return const StatementInferenceResult();
   }
 
@@ -7091,28 +6858,28 @@
     ExpressionInferenceResult expressionResult;
     DartType typeContext = closureContext.yieldContext;
     if (node.isYieldStar && typeContext is! UnknownType) {
-      typeContext = inferrer.wrapType(
+      typeContext = wrapType(
           typeContext,
           closureContext.isAsync
-              ? inferrer.coreTypes.streamClass
-              : inferrer.coreTypes.iterableClass,
-          inferrer.libraryBuilder.nonNullable);
+              ? coreTypes.streamClass
+              : coreTypes.iterableClass,
+          libraryBuilder.nonNullable);
     }
     expressionResult = inferExpression(node.expression, typeContext, true,
         isVoidAllowed: true);
-    closureContext.handleYield(inferrer, node, expressionResult);
+    closureContext.handleYield(node, expressionResult);
     return const StatementInferenceResult();
   }
 
   @override
   ExpressionInferenceResult visitLoadLibrary(
       covariant LoadLibraryImpl node, DartType typeContext) {
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .futureType(const DynamicType(), inferrer.libraryBuilder.nonNullable);
+    DartType inferredType = typeSchemaEnvironment.futureType(
+        const DynamicType(), libraryBuilder.nonNullable);
     if (node.arguments != null) {
-      FunctionType calleeType = new FunctionType(
-          [], inferredType, inferrer.libraryBuilder.nonNullable);
-      inferrer.inferInvocation(this, typeContext, node.fileOffset, calleeType,
+      FunctionType calleeType =
+          new FunctionType([], inferredType, libraryBuilder.nonNullable);
+      inferInvocation(this, typeContext, node.fileOffset, calleeType,
           node.arguments! as ArgumentsImpl);
     }
     return new ExpressionInferenceResult(inferredType, node);
@@ -7122,9 +6889,9 @@
       LoadLibraryTearOff node, DartType typeContext) {
     DartType inferredType = new FunctionType(
         [],
-        inferrer.typeSchemaEnvironment.futureType(
-            const DynamicType(), inferrer.libraryBuilder.nonNullable),
-        inferrer.libraryBuilder.nonNullable);
+        typeSchemaEnvironment.futureType(
+            const DynamicType(), libraryBuilder.nonNullable),
+        libraryBuilder.nonNullable);
     Expression replacement = new StaticTearOff(node.target)
       ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
@@ -7135,8 +6902,7 @@
       CheckLibraryIsLoaded node, DartType typeContext) {
     // TODO(cstefantsova): Figure out the suitable nullability for that.
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.objectRawType(inferrer.libraryBuilder.nullable),
-        node);
+        coreTypes.objectRawType(libraryBuilder.nullable), node);
   }
 
   ExpressionInferenceResult visitEquals(
@@ -7153,7 +6919,7 @@
     ExpressionInferenceResult leftResult =
         inferExpression(node.left, const UnknownType(), true);
     Map<DartType, NonPromotionReason> Function() whyNotPromoted =
-        inferrer.flowAnalysis.whyNotPromoted(leftResult.expression);
+        flowAnalysis.whyNotPromoted(leftResult.expression);
     return _computeBinaryExpression(
         node.fileOffset,
         typeContext,
@@ -7179,18 +6945,18 @@
       // -9223372036854775808.unary-() which should be a negative number.
       if (node.expression is IntJudgment) {
         IntJudgment receiver = node.expression as IntJudgment;
-        if (inferrer.isDoubleContext(typeContext)) {
+        if (isDoubleContext(typeContext)) {
           double? doubleValue = receiver.asDouble(negated: true);
           if (doubleValue != null) {
             Expression replacement = new DoubleLiteral(doubleValue)
               ..fileOffset = node.fileOffset;
-            DartType inferredType = inferrer.coreTypes
-                .doubleRawType(inferrer.libraryBuilder.nonNullable);
+            DartType inferredType =
+                coreTypes.doubleRawType(libraryBuilder.nonNullable);
             return new ExpressionInferenceResult(inferredType, replacement);
           }
         }
         Expression? error = checkWebIntLiteralsErrorIfUnexact(
-            inferrer, receiver.value, receiver.literal, receiver.fileOffset);
+            receiver.value, receiver.literal, receiver.fileOffset);
         if (error != null) {
           return new ExpressionInferenceResult(const DynamicType(), error);
         }
@@ -7198,19 +6964,19 @@
         ShadowLargeIntLiteral receiver =
             node.expression as ShadowLargeIntLiteral;
         if (!receiver.isParenthesized) {
-          if (inferrer.isDoubleContext(typeContext)) {
+          if (isDoubleContext(typeContext)) {
             double? doubleValue = receiver.asDouble(negated: true);
             if (doubleValue != null) {
               Expression replacement = new DoubleLiteral(doubleValue)
                 ..fileOffset = node.fileOffset;
-              DartType inferredType = inferrer.coreTypes
-                  .doubleRawType(inferrer.libraryBuilder.nonNullable);
+              DartType inferredType =
+                  coreTypes.doubleRawType(libraryBuilder.nonNullable);
               return new ExpressionInferenceResult(inferredType, replacement);
             }
           }
           int? intValue = receiver.asInt64(negated: true);
           if (intValue == null) {
-            Expression error = inferrer.helper.buildProblem(
+            Expression error = helper.buildProblem(
                 templateIntegerLiteralIsOutOfRange
                     .withArguments(receiver.literal),
                 receiver.fileOffset,
@@ -7220,13 +6986,12 @@
           // ignore: unnecessary_null_comparison
           if (intValue != null) {
             Expression? error = checkWebIntLiteralsErrorIfUnexact(
-                inferrer, intValue, receiver.literal, receiver.fileOffset);
+                intValue, receiver.literal, receiver.fileOffset);
             if (error != null) {
               return new ExpressionInferenceResult(const DynamicType(), error);
             }
             expressionResult = new ExpressionInferenceResult(
-                inferrer.coreTypes
-                    .intRawType(inferrer.libraryBuilder.nonNullable),
+                coreTypes.intRawType(libraryBuilder.nonNullable),
                 new IntLiteral(-intValue)
                   ..fileOffset = node.expression.fileOffset);
           }
@@ -7238,7 +7003,7 @@
           inferExpression(node.expression, const UnknownType(), true);
     }
     Map<DartType, NonPromotionReason> Function() whyNotPromoted =
-        inferrer.flowAnalysis.whyNotPromoted(expressionResult.expression);
+        flowAnalysis.whyNotPromoted(expressionResult.expression);
     return _computeUnaryExpression(node.fileOffset, expressionResult.expression,
         expressionResult.inferredType, node.unaryName, whyNotPromoted);
   }
@@ -7251,15 +7016,15 @@
 
   void reportNonNullableInNullAwareWarningIfNeeded(
       DartType operandType, String operationName, int offset) {
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
+    if (!isTopLevel && isNonNullableByDefault) {
       if (operandType is! InvalidType &&
           operandType.nullability == Nullability.nonNullable) {
-        inferrer.libraryBuilder.addProblem(
+        libraryBuilder.addProblem(
             templateNonNullableInNullAware.withArguments(
-                operationName, operandType, inferrer.isNonNullableByDefault),
+                operationName, operandType, isNonNullableByDefault),
             offset,
             noLength,
-            inferrer.helper.uri);
+            helper.uri);
       }
     }
   }
@@ -7281,11 +7046,11 @@
 
 abstract class ForInVariable {
   /// Computes the type of the elements expected for this for-in variable.
-  DartType computeElementType(InferenceVisitor visitor);
+  DartType computeElementType(InferenceVisitorBase visitor);
 
   /// Infers the assignment to this for-in variable with a value of type
   /// [rhsType]. The resulting expression is returned.
-  Expression? inferAssignment(InferenceVisitor visitor, DartType rhsType);
+  Expression? inferAssignment(InferenceVisitorBase visitor, DartType rhsType);
 }
 
 class LocalForInVariable implements ForInVariable {
@@ -7294,20 +7059,20 @@
   LocalForInVariable(this.variableSet);
 
   @override
-  DartType computeElementType(InferenceVisitor visitor) {
+  DartType computeElementType(InferenceVisitorBase visitor) {
     VariableDeclaration variable = variableSet.variable;
     DartType? promotedType;
-    if (visitor.inferrer.isNonNullableByDefault) {
-      promotedType = visitor.inferrer.flowAnalysis.promotedType(variable);
+    if (visitor.isNonNullableByDefault) {
+      promotedType = visitor.flowAnalysis.promotedType(variable);
     }
     return promotedType ?? variable.type;
   }
 
   @override
-  Expression inferAssignment(InferenceVisitor visitor, DartType rhsType) {
+  Expression inferAssignment(InferenceVisitorBase visitor, DartType rhsType) {
     DartType variableType =
-        visitor.inferrer.computeGreatestClosure(variableSet.variable.type);
-    Expression rhs = visitor.inferrer.ensureAssignable(
+        visitor.computeGreatestClosure(variableSet.variable.type);
+    Expression rhs = visitor.ensureAssignable(
         variableType, rhsType, variableSet.value,
         errorTemplate: templateForInLoopElementTypeNotAssignable,
         nullabilityErrorTemplate:
@@ -7317,7 +7082,7 @@
         isVoidAllowed: true);
 
     variableSet.value = rhs..parent = variableSet;
-    visitor.inferrer.flowAnalysis
+    visitor.flowAnalysis
         .write(variableSet, variableSet.variable, rhsType, null);
     return variableSet;
   }
@@ -7333,19 +7098,19 @@
   PropertyForInVariable(this.propertySet);
 
   @override
-  DartType computeElementType(InferenceVisitor visitor) {
+  DartType computeElementType(InferenceVisitorBase visitor) {
     ExpressionInferenceResult receiverResult = visitor.inferExpression(
         propertySet.receiver, const UnknownType(), true);
     propertySet.receiver = receiverResult.expression..parent = propertySet;
     DartType receiverType = receiverResult.inferredType;
-    ObjectAccessTarget writeTarget = visitor.inferrer.findInterfaceMember(
+    ObjectAccessTarget writeTarget = visitor.findInterfaceMember(
         receiverType, propertySet.name, propertySet.fileOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         instrumented: true,
         includeExtensionMethods: true);
     DartType elementType =
-        _writeType = visitor.inferrer.getSetterType(writeTarget, receiverType);
-    Expression? error = visitor.inferrer.reportMissingInterfaceMember(
+        _writeType = visitor.getSetterType(writeTarget, receiverType);
+    Expression? error = visitor.reportMissingInterfaceMember(
         writeTarget,
         receiverType,
         propertySet.name,
@@ -7355,10 +7120,10 @@
       _rhs = error;
     } else {
       if (writeTarget.isInstanceMember || writeTarget.isObjectMember) {
-        if (visitor.inferrer.instrumentation != null &&
+        if (visitor.instrumentation != null &&
             receiverType == const DynamicType()) {
-          visitor.inferrer.instrumentation!.record(
-              visitor.inferrer.uriForInstrumentation,
+          visitor.instrumentation!.record(
+              visitor.uriForInstrumentation,
               propertySet.fileOffset,
               'target',
               new InstrumentationValueForMember(writeTarget.member!));
@@ -7370,9 +7135,9 @@
   }
 
   @override
-  Expression inferAssignment(InferenceVisitor visitor, DartType rhsType) {
-    Expression rhs = visitor.inferrer.ensureAssignable(
-        visitor.inferrer.computeGreatestClosure(_writeType!), rhsType, _rhs!,
+  Expression inferAssignment(InferenceVisitorBase visitor, DartType rhsType) {
+    Expression rhs = visitor.ensureAssignable(
+        visitor.computeGreatestClosure(_writeType!), rhsType, _rhs!,
         errorTemplate: templateForInLoopElementTypeNotAssignable,
         nullabilityErrorTemplate:
             templateForInLoopElementTypeNotAssignableNullability,
@@ -7382,7 +7147,7 @@
 
     propertySet.value = rhs..parent = propertySet;
     ExpressionInferenceResult result = visitor.inferExpression(
-        propertySet, const UnknownType(), !visitor.inferrer.isTopLevel,
+        propertySet, const UnknownType(), !visitor.isTopLevel,
         isVoidAllowed: true);
     return result.expression;
   }
@@ -7396,23 +7161,22 @@
   AbstractSuperPropertyForInVariable(this.superPropertySet);
 
   @override
-  DartType computeElementType(InferenceVisitor visitor) {
-    DartType receiverType = visitor.inferrer.thisType!;
-    ObjectAccessTarget writeTarget = visitor.inferrer.findInterfaceMember(
+  DartType computeElementType(InferenceVisitorBase visitor) {
+    DartType receiverType = visitor.thisType!;
+    ObjectAccessTarget writeTarget = visitor.findInterfaceMember(
         receiverType, superPropertySet.name, superPropertySet.fileOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         instrumented: true);
     if (writeTarget.isInstanceMember || writeTarget.isObjectMember) {
       superPropertySet.interfaceTarget = writeTarget.member;
     }
-    return _writeType =
-        visitor.inferrer.getSetterType(writeTarget, receiverType);
+    return _writeType = visitor.getSetterType(writeTarget, receiverType);
   }
 
   @override
-  Expression inferAssignment(InferenceVisitor visitor, DartType rhsType) {
-    Expression rhs = visitor.inferrer.ensureAssignable(
-        visitor.inferrer.computeGreatestClosure(_writeType!),
+  Expression inferAssignment(InferenceVisitorBase visitor, DartType rhsType) {
+    Expression rhs = visitor.ensureAssignable(
+        visitor.computeGreatestClosure(_writeType!),
         rhsType,
         superPropertySet.value,
         errorTemplate: templateForInLoopElementTypeNotAssignable,
@@ -7423,7 +7187,7 @@
         isVoidAllowed: true);
     superPropertySet.value = rhs..parent = superPropertySet;
     ExpressionInferenceResult result = visitor.inferExpression(
-        superPropertySet, const UnknownType(), !visitor.inferrer.isTopLevel,
+        superPropertySet, const UnknownType(), !visitor.isTopLevel,
         isVoidAllowed: true);
     return result.expression;
   }
@@ -7437,23 +7201,22 @@
   SuperPropertyForInVariable(this.superPropertySet);
 
   @override
-  DartType computeElementType(InferenceVisitor visitor) {
-    DartType receiverType = visitor.inferrer.thisType!;
-    ObjectAccessTarget writeTarget = visitor.inferrer.findInterfaceMember(
+  DartType computeElementType(InferenceVisitorBase visitor) {
+    DartType receiverType = visitor.thisType!;
+    ObjectAccessTarget writeTarget = visitor.findInterfaceMember(
         receiverType, superPropertySet.name, superPropertySet.fileOffset,
         callSiteAccessKind: CallSiteAccessKind.setterInvocation,
         instrumented: true);
     if (writeTarget.isInstanceMember || writeTarget.isObjectMember) {
       superPropertySet.interfaceTarget = writeTarget.member;
     }
-    return _writeType =
-        visitor.inferrer.getSetterType(writeTarget, receiverType);
+    return _writeType = visitor.getSetterType(writeTarget, receiverType);
   }
 
   @override
-  Expression inferAssignment(InferenceVisitor visitor, DartType rhsType) {
-    Expression rhs = visitor.inferrer.ensureAssignable(
-        visitor.inferrer.computeGreatestClosure(_writeType!),
+  Expression inferAssignment(InferenceVisitorBase visitor, DartType rhsType) {
+    Expression rhs = visitor.ensureAssignable(
+        visitor.computeGreatestClosure(_writeType!),
         rhsType,
         superPropertySet.value,
         errorTemplate: templateForInLoopElementTypeNotAssignable,
@@ -7464,7 +7227,7 @@
         isVoidAllowed: true);
     superPropertySet.value = rhs..parent = superPropertySet;
     ExpressionInferenceResult result = visitor.inferExpression(
-        superPropertySet, const UnknownType(), !visitor.inferrer.isTopLevel,
+        superPropertySet, const UnknownType(), !visitor.isTopLevel,
         isVoidAllowed: true);
     return result.expression;
   }
@@ -7476,14 +7239,14 @@
   StaticForInVariable(this.staticSet);
 
   @override
-  DartType computeElementType(InferenceVisitor visitor) =>
+  DartType computeElementType(InferenceVisitorBase visitor) =>
       staticSet.target.setterType;
 
   @override
-  Expression inferAssignment(InferenceVisitor visitor, DartType rhsType) {
+  Expression inferAssignment(InferenceVisitorBase visitor, DartType rhsType) {
     DartType setterType =
-        visitor.inferrer.computeGreatestClosure(staticSet.target.setterType);
-    Expression rhs = visitor.inferrer.ensureAssignable(
+        visitor.computeGreatestClosure(staticSet.target.setterType);
+    Expression rhs = visitor.ensureAssignable(
         setterType, rhsType, staticSet.value,
         errorTemplate: templateForInLoopElementTypeNotAssignable,
         nullabilityErrorTemplate:
@@ -7494,7 +7257,7 @@
 
     staticSet.value = rhs..parent = staticSet;
     ExpressionInferenceResult result = visitor.inferExpression(
-        staticSet, const UnknownType(), !visitor.inferrer.isTopLevel,
+        staticSet, const UnknownType(), !visitor.isTopLevel,
         isVoidAllowed: true);
     return result.expression;
   }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index b07d750..c1748fb 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -278,34 +278,30 @@
         instrumentation = isTopLevel ? null : engine.instrumentation,
         typeSchemaEnvironment = engine.typeSchemaEnvironment {}
 
-  InferenceVisitor _createInferenceVisitor(InferenceVisitorBase inferrer) {
+  InferenceVisitorBase _createInferenceVisitor(InferenceHelper? helper) {
     // For full (non-top level) inference, we need access to the
-    // ExpressionGeneratorHelper so that we can perform error recovery.
-    assert(isTopLevel || inferrer._helper != null,
-        "Helper hasn't been set up for full inference.");
-    return new InferenceVisitor(inferrer);
+    // InferenceHelper so that we can perform error reporting.
+    return new InferenceVisitorImpl(this, helper);
   }
 
   @override
   DartType inferImplicitFieldType(
       InferenceHelper helper, Expression initializer) {
-    InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
-    InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+    InferenceVisitorBase visitor = _createInferenceVisitor(helper);
     ExpressionInferenceResult result = visitor.inferExpression(
         initializer, const UnknownType(), true,
         isVoidAllowed: true);
-    return inferrer.inferDeclarationType(result.inferredType);
+    return visitor.inferDeclarationType(result.inferredType);
   }
 
   @override
   ExpressionInferenceResult inferFieldInitializer(
       InferenceHelper helper, DartType declaredType, Expression initializer) {
     assert(!isTopLevel);
-    InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
-    InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+    InferenceVisitorBase visitor = _createInferenceVisitor(helper);
     ExpressionInferenceResult initializerResult = visitor
         .inferExpression(initializer, declaredType, true, isVoidAllowed: true);
-    initializerResult = inferrer.ensureAssignableResult(
+    initializerResult = visitor.ensureAssignableResult(
         declaredType, initializerResult,
         isVoidAllowed: declaredType is VoidType);
     return initializerResult;
@@ -316,10 +312,9 @@
       DartType returnType, AsyncMarker asyncMarker, Statement body) {
     // ignore: unnecessary_null_comparison
     assert(body != null);
-    InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+    InferenceVisitorBase visitor = _createInferenceVisitor(helper);
     ClosureContext closureContext =
-        new ClosureContext(inferrer, asyncMarker, returnType, false);
-    InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+        new ClosureContext(visitor, asyncMarker, returnType, false);
     StatementInferenceResult result =
         visitor.inferStatement(body, closureContext);
     if (dataForTesting != null) {
@@ -329,7 +324,7 @@
       }
     }
     result =
-        closureContext.handleImplicitReturn(inferrer, body, result, fileOffset);
+        closureContext.handleImplicitReturn(visitor, body, result, fileOffset);
     DartType? futureValueType = closureContext.futureValueType;
     assert(!(asyncMarker == AsyncMarker.Async && futureValueType == null),
         "No future value type computed.");
@@ -346,8 +341,7 @@
       int fileOffset,
       Member target,
       FunctionType targetType) {
-    InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
-    InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+    InferenceVisitorBase visitor = _createInferenceVisitor(helper);
     List<Expression> positionalArguments = <Expression>[];
     for (VariableDeclaration parameter
         in redirectingFactoryFunction.positionalParameters) {
@@ -368,7 +362,7 @@
         fileOffset, positionalArguments,
         named: namedArguments);
 
-    InvocationInferenceResult result = inferrer.inferInvocation(
+    InvocationInferenceResult result = visitor.inferInvocation(
         visitor, typeContext, fileOffset, targetType, targetInvocationArguments,
         staticTarget: target);
     DartType resultType = result.inferredType;
@@ -387,15 +381,8 @@
     // TODO(paulberry): experiment to see if dynamic dispatch would be better,
     // so that the type hierarchy will be simpler (which may speed up "is"
     // checks).
-    InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
-    InferenceVisitor visitor = _createInferenceVisitor(inferrer);
-    InitializerInferenceResult inferenceResult;
-    if (initializer is InitializerJudgment) {
-      inferenceResult = initializer.acceptInference(visitor);
-    } else {
-      inferenceResult = initializer.accept(visitor);
-    }
-    return inferenceResult;
+    InferenceVisitor visitor = _createInferenceVisitor(helper);
+    return visitor.inferInitializer(initializer);
   }
 
   @override
@@ -405,9 +392,8 @@
       // We bypass the check for assignment of the helper during top-level
       // inference and use `_helper = helper` instead of `this.helper = helper`
       // because inference on metadata requires the helper.
-      InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
-      InferenceVisitor visitor = _createInferenceVisitor(inferrer);
-      inferrer.inferMetadataKeepingHelper(visitor, parent, annotations);
+      InferenceVisitorBase visitor = _createInferenceVisitor(helper);
+      visitor.inferMetadata(visitor, parent, annotations);
     }
   }
 
@@ -419,24 +405,25 @@
       bool hasDeclaredInitializer) {
     // ignore: unnecessary_null_comparison
     assert(declaredType != null);
-    InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
-    InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+    InferenceVisitorBase visitor = _createInferenceVisitor(helper);
     ExpressionInferenceResult result =
         visitor.inferExpression(initializer, declaredType, true);
     if (hasDeclaredInitializer) {
       initializer =
-          inferrer.ensureAssignableResult(declaredType, result).expression;
+          visitor.ensureAssignableResult(declaredType, result).expression;
     }
     return initializer;
   }
 }
 
-class InferenceVisitorBase {
+abstract class InferenceVisitorBase implements InferenceVisitor {
   final TypeInferrerImpl _inferrer;
 
   final InferenceHelper? _helper;
 
-  InferenceVisitorBase(this._inferrer, this._helper);
+  InferenceVisitorBase(this._inferrer, this._helper)
+      : assert(_inferrer.isTopLevel || _helper != null,
+            "Helper hasn't been set up for full inference.");
 
   AssignedVariables<TreeNode, VariableDeclaration> get assignedVariables =>
       _inferrer.assignedVariables;
@@ -2800,7 +2787,7 @@
       for (int i = 0; i < positionalParameters.length; i++) {
         VariableDeclaration parameter = positionalParameters[i];
         flowAnalysis.declare(parameter, true);
-        inferMetadataKeepingHelper(visitor, parameter, parameter.annotations);
+        inferMetadata(visitor, parameter, parameter.annotations);
         if (parameter.initializer != null) {
           ExpressionInferenceResult initializerResult = visitor.inferExpression(
               parameter.initializer!, parameter.type, !isTopLevel);
@@ -2810,7 +2797,7 @@
       }
       for (VariableDeclaration parameter in function.namedParameters) {
         flowAnalysis.declare(parameter, true);
-        inferMetadataKeepingHelper(visitor, parameter, parameter.annotations);
+        inferMetadata(visitor, parameter, parameter.annotations);
         ExpressionInferenceResult initializerResult = visitor.inferExpression(
             parameter.initializer!, parameter.type, !isTopLevel);
         parameter.initializer = initializerResult.expression
@@ -2985,7 +2972,7 @@
     return function.computeFunctionType(libraryBuilder.nonNullable);
   }
 
-  void inferMetadataKeepingHelper(InferenceVisitor visitor, TreeNode? parent,
+  void inferMetadata(InferenceVisitor visitor, TreeNode? parent,
       List<Expression>? annotations) {
     if (annotations != null) {
       for (int index = 0; index < annotations.length; index++) {
@@ -4841,6 +4828,27 @@
       identical(result.inferredType, noInferredType) || isNonNullableByDefault
           ? result.inferredType
           : legacyErasure(result.inferredType);
+
+  Expression? checkWebIntLiteralsErrorIfUnexact(
+      int value, String? literal, int charOffset) {
+    if (value >= 0 && value <= (1 << 53)) return null;
+    if (isTopLevel) return null;
+    if (!libraryBuilder
+        .loader.target.backendTarget.errorOnUnexactWebIntLiterals) return null;
+    BigInt asInt = new BigInt.from(value).toUnsigned(64);
+    BigInt asDouble = new BigInt.from(asInt.toDouble());
+    if (asInt == asDouble) return null;
+    String text = literal ?? value.toString();
+    String nearest = text.startsWith('0x') || text.startsWith('0X')
+        ? '0x${asDouble.toRadixString(16)}'
+        : asDouble.toString();
+    int length = literal?.length ?? noLength;
+    return helper.buildProblem(
+        templateWebLiteralCannotBeRepresentedExactly.withArguments(
+            text, nearest),
+        charOffset,
+        length);
+  }
 }
 
 class TypeInferrerImplBenchmarked implements TypeInferrer {
diff --git a/pkg/test_runner/bin/compare_results.dart b/pkg/test_runner/bin/compare_results.dart
index 39eb614..15a11c2 100755
--- a/pkg/test_runner/bin/compare_results.dart
+++ b/pkg/test_runner/bin/compare_results.dart
@@ -7,8 +7,6 @@
 // The output contains additional details in the verbose mode. There is a human
 // readable mode that explains the results and how they changed.
 
-// @dart = 2.9
-
 import 'dart:collection';
 import 'dart:io';
 
@@ -16,7 +14,7 @@
 import 'package:test_runner/bot_results.dart';
 
 class Event {
-  final Result before;
+  final Result? before;
   final Result after;
 
   Event(this.before, this.after);
@@ -27,13 +25,13 @@
   bool get changed => !unchanged;
   bool get unchanged =>
       before != null &&
-      before.outcome == after.outcome &&
-      before.expectation == after.expectation;
-  bool get remainedPassing => before.matches && after.matches;
-  bool get remainedFailing => !before.matches && !after.matches;
+      before!.outcome == after.outcome &&
+      before!.expectation == after.expectation;
+  bool get remainedPassing => before!.matches && after.matches;
+  bool get remainedFailing => !before!.matches && !after.matches;
   bool get flaked => after.flaked;
-  bool get fixed => !before.matches && after.matches;
-  bool get broke => before.matches && !after.matches;
+  bool get fixed => !before!.matches && after.matches;
+  bool get broke => before!.matches && !after.matches;
 
   String get description {
     if (isNewPassing) {
@@ -60,14 +58,14 @@
   final ArgResults _options;
 
   bool get changed => _options["changed"] as bool;
-  int get count => _options["count"] is String
+  int? get count => _options["count"] is String
       ? int.parse(_options["count"] as String)
       : null;
-  String get flakinessData => _options["flakiness-data"] as String;
+  String? get flakinessData => _options["flakiness-data"] as String?;
   bool get help => _options["help"] as bool;
   bool get human => _options["human"] as bool;
   bool get judgement => _options["judgement"] as bool;
-  String get logs => _options["logs"] as String;
+  String? get logs => _options["logs"] as String?;
   bool get logsOnly => _options["logs-only"] as bool;
   Iterable<String> get statusFilter => ["passing", "flaky", "failing"]
       .where((option) => _options[option] as bool);
@@ -81,16 +79,16 @@
 bool search(
     String description,
     String searchForStatus,
-    List<Event> events,
+    Iterable<Event> events,
     Options options,
     Map<String, Map<String, dynamic>> logs,
-    List<String> logSection) {
+    List<String>? logSection) {
   var judgement = false;
   var beganSection = false;
   var count = options.count;
-  final configurations =
-      events.map((event) => event.after.configuration).toSet();
+  final configurations = <String>{};
   for (final event in events) {
+    configurations.add(event.after.configuration);
     if (searchForStatus == "passing" &&
         (event.after.flaked || !event.after.matches)) {
       continue;
@@ -236,10 +234,10 @@
   final after = await loadResultsMap(parameters[1]);
   final logs = options.logs == null
       ? <String, Map<String, dynamic>>{}
-      : await loadResultsMap(options.logs);
-  final flakinessData = options.flakinessData != null
-      ? await loadResultsMap(options.flakinessData)
-      : <String, Map<String, dynamic>>{};
+      : await loadResultsMap(options.logs!);
+  final flakinessData = options.flakinessData == null
+      ? <String, Map<String, dynamic>>{}
+      : await loadResultsMap(options.flakinessData!);
 
   // The names of every test that has a data point in the new data set.
   final names = SplayTreeSet<String>.from(after.keys);
@@ -247,7 +245,7 @@
   final events = <Event>[];
   for (final name in names) {
     final mapBefore = before[name];
-    final mapAfter = after[name];
+    final mapAfter = after[name]!;
     final resultBefore = mapBefore != null
         ? Result.fromMap(mapBefore, flakinessData[name])
         : null;
@@ -291,7 +289,7 @@
         : options.changed
             ? "changed"
             : null;
-    final aboutStatus = filterDescriptions[searchForStatus][searchForChanged];
+    final aboutStatus = filterDescriptions[searchForStatus]![searchForChanged];
     final sectionHeader = "The following tests $aboutStatus:";
     final logSectionArg =
         searchForStatus == "failing" || searchForStatus == "flaky"
@@ -299,7 +297,7 @@
             : null;
     final possibleJudgement = search(
         sectionHeader, searchForStatus, events, options, logs, logSectionArg);
-    if (searchForStatus == null || searchForStatus == "failing") {
+    if (searchForStatus == "failing") {
       judgement = possibleJudgement;
     }
   }
diff --git a/pkg/test_runner/bin/http_server.dart b/pkg/test_runner/bin/http_server.dart
index a6eeacc..cd2d834 100644
--- a/pkg/test_runner/bin/http_server.dart
+++ b/pkg/test_runner/bin/http_server.dart
@@ -37,7 +37,7 @@
         args['csp'] as bool,
         Runtime.find(args['runtime'] as String),
         null,
-        args['packages'] as String);
+        args['packages'] as String?);
     var port = int.parse(args['port'] as String);
     var crossOriginPort = int.parse(args['crossOriginPort'] as String);
     servers
diff --git a/pkg/test_runner/bin/launch_browser.dart b/pkg/test_runner/bin/launch_browser.dart
index 4b81a69..ba4da38 100644
--- a/pkg/test_runner/bin/launch_browser.dart
+++ b/pkg/test_runner/bin/launch_browser.dart
@@ -33,8 +33,10 @@
 
   var runtime = Runtime.find(name);
   var configuration = TestConfiguration(
-      configuration: Configuration(
-          "dummy-configuration", null, null, null, runtime, null));
+      configuration: Configuration("dummy-configuration", Architecture.x64,
+          Compiler.none, Mode.release, runtime, System.host),
+      outputDirectory: 'dummy',
+      reproducingArguments: []);
   var browser = Browser.fromConfiguration(configuration);
   browser.start(arguments[1]);
 }
diff --git a/pkg/test_runner/bin/test_runner.dart b/pkg/test_runner/bin/test_runner.dart
index e21cfb5..bd1027a 100644
--- a/pkg/test_runner/bin/test_runner.dart
+++ b/pkg/test_runner/bin/test_runner.dart
@@ -31,19 +31,15 @@
   // Parse the command line arguments to a configuration.
   final parser = OptionsParser();
 
-  List<TestConfiguration> configurations;
+  late List<TestConfiguration> configurations;
   try {
     configurations = parser.parse(arguments);
   } on OptionParseException catch (exception) {
     print(exception.message);
     exit(1);
   }
-  if (configurations == null) {
-    return;
-  }
-
-  final build_success = await buildConfigurations(configurations);
-  if (!build_success) {
+  final buildSuccess = await buildConfigurations(configurations);
+  if (!buildSuccess) {
     print("ERROR: Build failed.");
     exit(1);
   }
diff --git a/pkg/test_runner/lib/bot_results.dart b/pkg/test_runner/lib/bot_results.dart
index 8f68b04..1bad14e 100644
--- a/pkg/test_runner/lib/bot_results.dart
+++ b/pkg/test_runner/lib/bot_results.dart
@@ -12,7 +12,7 @@
 import 'package:pool/pool.dart';
 
 /// The path to the gsutil script.
-String gsutilPy;
+late String gsutilPy;
 
 // TODO(karlklose):  Update this class with all fields that
 // are used in pkg/test_runner and the tools/bots scripts and include
@@ -42,7 +42,8 @@
       this.previousOutcome,
       [this.flaked = false]);
 
-  Result.fromMap(Map<String, dynamic> map, [Map<String, dynamic> flakinessData])
+  Result.fromMap(Map<String, dynamic> map,
+      [Map<String, dynamic>? flakinessData])
       : configuration = map["configuration"] as String,
         name = map["name"] as String,
         outcome = map["result"] as String,
@@ -73,11 +74,11 @@
     var processResult = await Process.run(
         "python3", [gsutilPy]..addAll(arguments),
         runInShell: Platform.isWindows);
-    var stderr = processResult.stderr as String;
     if (processResult.exitCode != 0) {
+      var stderr = processResult.stderr as String;
       if (processResult.exitCode == 1 && stderr.contains("No URLs matched") ||
           stderr.contains("One or more URLs matched no objects")) {
-        return null;
+        return "";
       }
       var error = "Failed to run: python3 $gsutilPy $arguments\n"
           "exitCode: ${processResult.exitCode}\n"
@@ -102,8 +103,8 @@
 /// or null if it didn't exist.
 Future<Iterable<String>> lsGsutil(String directory) async {
   var contents = await runGsutil(["ls", directory]);
-  if (contents == null) {
-    return null;
+  if (contents.isEmpty) {
+    return const [];
   }
   return LineSplitter.split(contents).map((String path) {
     var elements = path.split("/");
diff --git a/pkg/test_runner/lib/src/android.dart b/pkg/test_runner/lib/src/android.dart
index 0797ea6..f7ca3bd 100644
--- a/pkg/test_runner/lib/src/android.dart
+++ b/pkg/test_runner/lib/src/android.dart
@@ -38,7 +38,7 @@
 /// If the exit code of the process was nonzero it will complete with an error.
 /// If starting the process failed, it will complete with an error as well.
 Future<AdbCommandResult> _executeCommand(String executable, List<String> args,
-    {String stdin, Duration timeout}) {
+    {String? stdin, Duration? timeout}) {
   Future<String> getOutput(Stream<List<int>> stream) {
     return stream
         .transform(utf8.decoder)
@@ -53,7 +53,7 @@
     }
     process.stdin.close();
 
-    Timer timer;
+    Timer? timer;
     var timedOut = false;
     if (timeout != null) {
       timer = Timer(timeout, () {
@@ -68,7 +68,7 @@
       getOutput(process.stderr),
       process.exitCode
     ]);
-    if (timer != null) timer.cancel();
+    timer?.cancel();
 
     var command = "$executable ${args.join(' ')}";
     return AdbCommandResult(command, results[0] as String, results[1] as String,
@@ -205,7 +205,9 @@
       // TODO: Figure out a way to wait until the adb daemon was restarted in
       // 'root mode' on the device.
       Timer(_adbServerStartupTime, () => adbRootCompleter.complete(true));
-    }).catchError((error) => adbRootCompleter.completeError(error));
+    }).catchError((Object error) {
+      adbRootCompleter.completeError(error);
+    });
     return adbRootCompleter.future;
   }
 
@@ -253,7 +255,7 @@
       intent.action,
       '-n',
       "${intent.package}/${intent.activity}",
-      if (intent.dataUri != null) ...['-d', intent.dataUri]
+      if (intent.dataUri != null) ...['-d', intent.dataUri!]
     ]);
   }
 
@@ -273,13 +275,13 @@
   }
 
   Future<AdbCommandResult> runAdbCommand(List<String> adbArgs,
-      {Duration timeout}) {
+      {Duration? timeout}) {
     return _executeCommand("adb", _deviceSpecificArgs(adbArgs),
         timeout: timeout);
   }
 
   Future<AdbCommandResult> runAdbShellCommand(List<String> shellArgs,
-      {Duration timeout}) async {
+      {Duration? timeout}) async {
     const marker = 'AdbShellExitCode: ';
 
     // The exitcode of 'adb shell ...' can be 0 even though the command failed
@@ -332,12 +334,7 @@
   }
 
   List<String> _deviceSpecificArgs(List<String> adbArgs) {
-    if (deviceId != null) {
-      var extendedAdbArgs = ['-s', deviceId];
-      extendedAdbArgs.addAll(adbArgs);
-      adbArgs = extendedAdbArgs;
-    }
-    return adbArgs;
+    return ['-s', deviceId, ...adbArgs];
   }
 }
 
@@ -354,7 +351,7 @@
       }
       return _deviceLineRegexp
           .allMatches(result.stdout as String)
-          .map((Match m) => m.group(1))
+          .map((Match m) => m.group(1)!)
           .toList();
     });
   }
@@ -365,7 +362,7 @@
   String action;
   String package;
   String activity;
-  String dataUri;
+  String? dataUri;
 
   Intent(this.action, this.package, this.activity, [this.dataUri]);
 }
diff --git a/pkg/test_runner/lib/src/browser.dart b/pkg/test_runner/lib/src/browser.dart
index f7174a2..c38a66d 100644
--- a/pkg/test_runner/lib/src/browser.dart
+++ b/pkg/test_runner/lib/src/browser.dart
@@ -58,19 +58,9 @@
   if (name.isEmpty) return r'$';
 
   // Escape any invalid characters
-  StringBuffer buffer;
-  for (var i = 0; i < name.length; i++) {
-    var ch = name[i];
-    var needsEscape = ch == r'$' || _invalidCharInIdentifier.hasMatch(ch);
-    if (needsEscape && buffer == null) {
-      buffer = StringBuffer(name.substring(0, i));
-    }
-    if (buffer != null) {
-      buffer.write(needsEscape ? '\$${ch.codeUnits.join("")}' : ch);
-    }
-  }
+  var result = name.replaceAllMapped(_invalidCharInIdentifier,
+      (match) => '\$${match.group(0)!.codeUnits.join("")}');
 
-  var result = buffer != null ? '$buffer' : name;
   // Ensure the identifier first character is not numeric and that the whole
   // identifier is not a keyword.
   if (result.startsWith(RegExp('[0-9]')) || _invalidVariableName(result)) {
@@ -80,7 +70,7 @@
 }
 
 // Invalid characters for identifiers, which would need to be escaped.
-final _invalidCharInIdentifier = RegExp(r'[^A-Za-z_$0-9]');
+final _invalidCharInIdentifier = RegExp(r'[^A-Za-z_0-9]');
 
 bool _invalidVariableName(String keyword, {bool strictMode = true}) {
   switch (keyword) {
diff --git a/pkg/test_runner/lib/src/browser_controller.dart b/pkg/test_runner/lib/src/browser_controller.dart
index a6c8b8a..c4300ee 100644
--- a/pkg/test_runner/lib/src/browser_controller.dart
+++ b/pkg/test_runner/lib/src/browser_controller.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
-import 'dart:math';
 
 import 'package:webdriver/io.dart';
 
@@ -18,7 +17,7 @@
 typedef BrowserDoneCallback = void Function(BrowserTestOutput output);
 typedef TestChangedCallback = void Function(
     String browserId, String output, int testId);
-typedef NextTestCallback = BrowserTest Function(String browserId);
+typedef NextTestCallback = BrowserTest? Function(String browserId);
 
 class BrowserOutput {
   final StringBuffer stdout = StringBuffer();
@@ -28,6 +27,9 @@
 
 /// Class describing the interface for communicating with browsers.
 abstract class Browser {
+  static int _browserIdCounter = 1;
+  static String _nextBrowserId() => "BROWSER${_browserIdCounter++}";
+
   /// Get the output that was written so far to stdout/stderr/eventLog.
   BrowserOutput get testBrowserOutput => _testBrowserOutput;
   BrowserOutput _testBrowserOutput = BrowserOutput();
@@ -38,7 +40,7 @@
   /// Subclasses can use this to cleanup any browser specific resources
   /// (temp directories, profiles, etc). The function is expected to do
   /// it's work synchronously.
-  Function _cleanup;
+  void Function()? _cleanup;
 
   /// The version of the browser - normally set when starting a browser
   Future<String> get version;
@@ -46,12 +48,12 @@
   /// The underlying process - don't mess directly with this if you don't
   /// know what you are doing (this is an interactive process that needs
   /// special treatment to not leak).
-  Process process;
+  Process? process;
 
-  Function logger;
+  void Function(String)? logger;
 
   /// Id of the browser.
-  String id;
+  final String id = _nextBrowserId();
 
   /// Reset the browser to a known configuration on start-up.
   /// Browser specific implementations are free to ignore this.
@@ -62,7 +64,7 @@
 
   /// This future returns when the process exits. It is also the return value
   /// of close()
-  Future<bool> done;
+  Future<bool>? done;
 
   Browser();
 
@@ -113,7 +115,7 @@
   void _logEvent(String event) {
     var toLog = "$this ($id) - $event \n";
     if (debugPrint) print("usageLog: $toLog");
-    if (logger != null) logger(toLog);
+    logger?.call(toLog);
 
     _testBrowserOutput.eventLog.write(toLog);
   }
@@ -133,12 +135,12 @@
   Future<bool> close() {
     _logEvent("Close called on browser");
     if (process != null) {
-      if (process.kill(ProcessSignal.sigkill)) {
+      if (process!.kill(ProcessSignal.sigkill)) {
         _logEvent("Successfully sent kill signal to process.");
       } else {
         _logEvent("Sending kill signal failed.");
       }
-      return done;
+      return done ?? Future.value(true);
     } else {
       _logEvent("The process is already dead.");
       return Future.value(true);
@@ -148,7 +150,7 @@
   /// Start the browser using the supplied argument.
   /// This sets up the error handling and usage logging.
   Future<bool> startBrowserProcess(String command, List<String> arguments,
-      {Map<String, String> environment}) {
+      {Map<String, String>? environment}) {
     return Process.start(command, arguments, environment: environment)
         .then((startedProcess) {
       _logEvent("Started browser using $command ${arguments.join(' ')}");
@@ -169,15 +171,15 @@
       // This timer is used to close stdio to the subprocess once we got
       // the exitCode. Sometimes descendants of the subprocess keep stdio
       // handles alive even though the direct subprocess is dead.
-      Timer watchdogTimer;
+      Timer? watchdogTimer;
 
       void closeStdout([_]) {
         if (!stdoutIsDone) {
           stdoutDone.complete();
           stdoutIsDone = true;
 
-          if (stderrIsDone && watchdogTimer != null) {
-            watchdogTimer.cancel();
+          if (stderrIsDone) {
+            watchdogTimer?.cancel();
           }
         }
       }
@@ -187,13 +189,13 @@
           stderrDone.complete();
           stderrIsDone = true;
 
-          if (stdoutIsDone && watchdogTimer != null) {
-            watchdogTimer.cancel();
+          if (stdoutIsDone) {
+            watchdogTimer?.cancel();
           }
         }
       }
 
-      stdoutSubscription = process.stdout
+      stdoutSubscription = process!.stdout
           .transform(utf8.decoder)
           .listen(_addStdout, onError: (error) {
         // This should _never_ happen, but we really want this in the log
@@ -201,7 +203,7 @@
         _logEvent("An error occurred in the process stdout handling: $error");
       }, onDone: closeStdout);
 
-      stderrSubscription = process.stderr
+      stderrSubscription = process!.stderr
           .transform(utf8.decoder)
           .listen(_addStderr, onError: (error) {
         // This should _never_ happen, but we really want this in the log
@@ -209,7 +211,7 @@
         _logEvent("An error occurred in the process stderr handling: $error");
       }, onDone: closeStderr);
 
-      process.exitCode.then((exitCode) {
+      process!.exitCode.then((exitCode) {
         _logEvent("Browser closed with exitcode $exitCode");
 
         if (!stdoutIsDone || !stderrIsDone) {
@@ -225,9 +227,7 @@
 
         Future.wait([stdoutDone.future, stderrDone.future]).then((_) {
           process = null;
-          if (_cleanup != null) {
-            _cleanup();
-          }
+          _cleanup?.call();
         }).catchError((error) {
           _logEvent("Error closing browsers: $error");
         }).whenComplete(() => doneCompleter.complete(true));
@@ -263,7 +263,7 @@
 }
 
 abstract class WebDriverBrowser extends Browser {
-  WebDriver _driver;
+  WebDriver? _driver;
   final int _port;
   final Map<String, dynamic> _desiredCapabilities;
 
@@ -273,7 +273,7 @@
   Future<bool> start(String url) async {
     _logEvent('Starting $this browser on: $url');
     await _createDriver();
-    await _driver.get(url);
+    await _driver!.get(url);
     try {
       _logEvent('Got version: ${await version}');
     } catch (error) {
@@ -354,8 +354,6 @@
 
   final String _binary;
 
-  Map<String, String> _getEnvironment() => null;
-
   @override
   Future<String> get version async {
     if (Platform.isWindows) {
@@ -418,7 +416,7 @@
       // is spawned. Handy for debugging tests.
       // args.add("--auto-open-devtools-for-tabs");
 
-      return startBrowserProcess(_binary, args, environment: _getEnvironment());
+      return startBrowserProcess(_binary, args);
     } catch (e) {
       _logEvent("Starting chrome failed with $e");
       return false;
@@ -491,7 +489,7 @@
   }
 
   Future<void> _setRegistryKey(String key, String value,
-      {String data, String type}) async {
+      {String? data, String? type}) async {
     var args = <String>[
       "add",
       key,
@@ -562,13 +560,10 @@
   }
 
   @override
-  Future<bool> close() {
-    if (_adbDevice != null) {
-      return _adbDevice.forceStop(chromePackage).then((_) {
-        return _adbDevice.killAll().then((_) => true);
-      });
-    }
-    return Future.value(true);
+  Future<bool> close() async {
+    await _adbDevice.forceStop(chromePackage);
+    await _adbDevice.killAll();
+    return true;
   }
 
   void logBrowserInfoToTestBrowserOutput() {
@@ -646,14 +641,14 @@
 /// Describes the current state of a browser used for testing.
 class BrowserStatus {
   Browser browser;
-  BrowserTest currentTest;
+  BrowserTest? currentTest;
 
   // This is currently not used for anything except for error reporting.
   // Given the usefulness of this in debugging issues this should not be
   // removed even when we have a really stable system.
-  BrowserTest lastTest;
+  BrowserTest? lastTest;
   bool timeout = false;
-  Timer nextTestTimeout;
+  Timer? nextTestTimeout;
   Stopwatch timeSinceRestart = Stopwatch()..start();
 
   BrowserStatus(this.browser);
@@ -666,30 +661,27 @@
   String url;
   int timeout;
   String lastKnownMessage = '';
-  Stopwatch stopwatch;
+  late Stopwatch stopwatch;
 
-  // This might be null
-  Duration delayUntilTestStarted;
+  Duration? delayUntilTestStarted;
 
   // We store this here for easy access when tests time out (instead of
   // capturing this in a closure)
-  Timer timeoutTimer;
+  late Timer timeoutTimer;
 
   // Used for debugging, this is simply a unique identifier assigned to each
   // test.
-  int id;
+  final int id = _idCounter++;
   static int _idCounter = 0;
 
-  BrowserTest(this.url, this.doneCallback, this.timeout) {
-    id = _idCounter++;
-  }
+  BrowserTest(this.url, this.doneCallback, this.timeout);
 
   String toJSON() => jsonEncode({'url': url, 'id': id});
 }
 
 /* Describes the output of running the test in a browser */
 class BrowserTestOutput {
-  final Duration delayUntilTestStarted;
+  final Duration? delayUntilTestStarted;
   final Duration duration;
 
   final String lastKnownMessage;
@@ -724,24 +716,22 @@
   final Browser Function(TestConfiguration configuration) browserFactory;
 
   final String localIp;
-  int maxNumBrowsers;
+  final int maxNumBrowsers;
   int numBrowsers = 0;
 
   /// Used to send back logs from the browser (start, stop etc.).
-  Function logger;
-
-  static int browserIdCounter = 1;
+  void Function(String)? logger;
 
   bool testingServerStarted = false;
   bool underTermination = false;
   int numBrowserGetTestTimeouts = 0;
   DateTime lastEmptyTestQueueTime = DateTime.now();
-  String _currentStartingBrowserId;
+  String? _currentStartingBrowserId;
   List<BrowserTest> testQueue = [];
   Map<String, BrowserStatus> browserStatus = {};
 
   Map<String, AdbDevice> adbDeviceMapping = {};
-  List<AdbDevice> idleAdbDevices;
+  late List<AdbDevice> idleAdbDevices;
 
   /// This cache is used to guarantee that we never see double reporting.
   /// If we do we need to provide developers with this information.
@@ -779,20 +769,16 @@
     testingServer.testRunner = this;
   }
 
-  Future<bool> start() async {
+  Future<BrowserTestRunner> start() async {
     await testingServer.start();
     testingServer
       ..testDoneCallBack = handleResults
       ..testStatusUpdateCallBack = handleStatusUpdate
       ..testStartedCallBack = handleStarted
       ..nextTestCallBack = getNextTest;
-    if (configuration.runtime == Runtime.chromeOnAndroid) {
-      var idbNames = await AdbHelper.listDevices();
-      idleAdbDevices = List.from(idbNames.map((id) => AdbDevice(id)));
-      maxNumBrowsers = min(maxNumBrowsers, idleAdbDevices.length);
-    }
     testingServerStarted = true;
-    return requestBrowser();
+    requestBrowser();
+    return this;
   }
 
   /// requestBrowser() is called whenever we might want to start an additional
@@ -803,38 +789,31 @@
   /// finishes a test.
   /// So we are guaranteed that this will always eventually be called, as long
   /// as the test queue isn't empty.
-  Future<bool> requestBrowser() async {
-    if (!testingServerStarted) return false;
-    if (underTermination) return false;
-    if (numBrowsers == maxNumBrowsers) return false;
-    if (aBrowserIsCurrentlyStarting) return false;
-    if (numBrowsers > 0 && queueWasEmptyRecently) return false;
-    return createBrowser();
+  void requestBrowser() {
+    if (!testingServerStarted) return;
+    if (underTermination) return;
+    if (numBrowsers == maxNumBrowsers) return;
+    if (aBrowserIsCurrentlyStarting) return;
+    if (numBrowsers > 0 && queueWasEmptyRecently) return;
+    createBrowser();
   }
 
-  static String getNextBrowserId() => "BROWSER${browserIdCounter++}";
-
   Future<bool> createBrowser() {
-    var id = getNextBrowserId();
-    var url = testingServer.getDriverUrl(id);
-
     Browser browser;
     if (configuration.runtime == Runtime.chromeOnAndroid) {
       var device = idleAdbDevices.removeLast();
-      adbDeviceMapping[id] = device;
       browser = AndroidChrome(device);
+      adbDeviceMapping[browser.id] = device;
     } else {
       browser = browserFactory(configuration);
       browser.logger = logger;
     }
-
-    browser.id = id;
-    markCurrentlyStarting(id);
+    markCurrentlyStarting(browser.id);
     var status = BrowserStatus(browser);
-    browserStatus[id] = status;
+    browserStatus[browser.id] = status;
     numBrowsers++;
     status.nextTestTimeout = createNextTestTimer(status);
-    return browser.start(url);
+    return browser.start(testingServer.getDriverUrl(browser.id));
   }
 
   void handleResults(String browserId, String output, int testId) {
@@ -844,38 +823,34 @@
       return;
     }
 
+    var test = status?.currentTest;
     if (status == null || status.timeout) {
       // We don't do anything, this browser is currently being killed and
       // replaced. The browser here can be null if we decided to kill the
       // browser.
-    } else if (status.currentTest != null) {
-      status.currentTest.timeoutTimer.cancel();
-      status.currentTest.stopwatch.stop();
+    } else if (test != null) {
+      test.timeoutTimer.cancel();
+      test.stopwatch.stop();
 
-      if (status.currentTest.id != testId) {
-        print("Expected test id ${status.currentTest.id} for"
-            "${status.currentTest.url}");
+      if (test.id != testId) {
+        print("Expected test id ${test.id} for ${test.url}");
         print("Got test id $testId");
-        print("Last test id was ${status.lastTest.id} for "
-            "${status.currentTest.url}");
+        print("Last test id was ${status.lastTest?.id} for ${test.url}");
         throw "This should never happen, wrong test id";
       }
-      testCache[testId] = status.currentTest.url;
+      testCache[testId] = test.url;
 
       // Report that the test is finished now
-      var browserTestOutput = BrowserTestOutput(
-          status.currentTest.delayUntilTestStarted,
-          status.currentTest.stopwatch.elapsed,
-          output,
-          status.browser.testBrowserOutput);
-      status.currentTest.doneCallback(browserTestOutput);
+      var browserTestOutput = BrowserTestOutput(test.delayUntilTestStarted,
+          test.stopwatch.elapsed, output, status.browser.testBrowserOutput);
+      test.doneCallback(browserTestOutput);
 
-      status.lastTest = status.currentTest;
+      status.lastTest = test;
       status.currentTest = null;
       status.nextTestTimeout = createNextTestTimer(status);
     } else {
       print("\nThis is bad, should never happen, handleResult no test");
-      print("URL: ${status.lastTest.url}");
+      print("URL: ${status.lastTest?.url}");
       print(output);
       terminate().then((_) {
         exit(1);
@@ -890,21 +865,21 @@
       // We don't do anything, this browser is currently being killed and
       // replaced. The browser here can be null if we decided to kill the
       // browser.
-    } else if (status.currentTest != null && status.currentTest.id == testId) {
-      status.currentTest.lastKnownMessage = output;
+    } else if (status.currentTest?.id == testId) {
+      status.currentTest!.lastKnownMessage = output;
     }
   }
 
   void handleStarted(String browserId, String output, int testId) {
     var status = browserStatus[browserId];
+    if (status == null || status.timeout) return;
 
-    if (status != null && !status.timeout && status.currentTest != null) {
-      status.currentTest.timeoutTimer.cancel();
-      status.currentTest.timeoutTimer =
-          createTimeoutTimer(status.currentTest, status);
-      status.currentTest.delayUntilTestStarted =
-          status.currentTest.stopwatch.elapsed;
-    }
+    var currentTest = status.currentTest;
+    if (currentTest == null) return;
+
+    currentTest.timeoutTimer.cancel();
+    currentTest.timeoutTimer = createTimeoutTimer(currentTest, status);
+    currentTest.delayUntilTestStarted = currentTest.stopwatch.elapsed;
   }
 
   Future handleTimeout(BrowserStatus status) async {
@@ -915,29 +890,30 @@
       return;
     }
     status.timeout = true;
-    timedOut.add(status.currentTest.url);
+    var currentTest = status.currentTest!;
+    timedOut.add(currentTest.url);
     var id = status.browser.id;
 
-    status.currentTest.stopwatch.stop();
+    currentTest.stopwatch.stop();
     await status.browser.close();
     var lastKnownMessage =
         'Dom could not be fetched, since the test timed out.';
-    if (status.currentTest.lastKnownMessage.isNotEmpty) {
-      lastKnownMessage = status.currentTest.lastKnownMessage;
+    if (currentTest.lastKnownMessage.isNotEmpty) {
+      lastKnownMessage = currentTest.lastKnownMessage;
     }
     if (status.lastTest != null) {
-      lastKnownMessage += '\nPrevious test was ${status.lastTest.url}';
+      lastKnownMessage += '\nPrevious test was ${status.lastTest!.url}';
     }
     // Wait until the browser is closed before reporting the test as timeout.
     // This will enable us to capture stdout/stderr from the browser
     // (which might provide us with information about what went wrong).
     var browserTestOutput = BrowserTestOutput(
-        status.currentTest.delayUntilTestStarted,
-        status.currentTest.stopwatch.elapsed,
+        currentTest.delayUntilTestStarted,
+        currentTest.stopwatch.elapsed,
         lastKnownMessage,
         status.browser.testBrowserOutput,
         didTimeout: true);
-    status.currentTest.doneCallback(browserTestOutput);
+    currentTest.doneCallback(browserTestOutput);
     status.lastTest = status.currentTest;
     status.currentTest = null;
 
@@ -951,21 +927,19 @@
   /// open browsers. Check if we want to replace it with a new browser.
   void removeBrowser(String id) {
     if (configuration.runtime == Runtime.chromeOnAndroid) {
-      idleAdbDevices.add(adbDeviceMapping.remove(id));
+      idleAdbDevices.add(adbDeviceMapping.remove(id)!);
     }
     markNotCurrentlyStarting(id);
     browserStatus.remove(id);
     --numBrowsers;
   }
 
-  BrowserTest getNextTest(String browserId) {
+  BrowserTest? getNextTest(String browserId) {
     markNotCurrentlyStarting(browserId);
     var status = browserStatus[browserId];
     if (status == null) return null;
-    if (status.nextTestTimeout != null) {
-      status.nextTestTimeout.cancel();
-      status.nextTestTimeout = null;
-    }
+    status.nextTestTimeout?.cancel();
+    status.nextTestTimeout = null;
     if (testQueue.isEmpty) return null;
 
     // We are currently terminating this browser, don't start a new test.
@@ -997,14 +971,11 @@
     } else {
       requestBrowser();
     }
-    if (status.currentTest == null) {
-      status.currentTest = test;
-      status.currentTest.lastKnownMessage = '';
-    } else {
+    if (status.currentTest != null) {
       // TODO(ricow): Handle this better.
       print("Browser requested next test before reporting previous result");
       print("This happened for browser $browserId");
-      print("Old test was: ${status.currentTest.url}");
+      print("Old test was: ${status.currentTest!.url}");
       print("The test before that was: ${status.lastTest?.url}");
       print("Timed out tests:");
       for (var v in timedOut) {
@@ -1012,9 +983,10 @@
       }
       exit(1);
     }
-
-    status.currentTest.timeoutTimer = createTimeoutTimer(test, status);
-    status.currentTest.stopwatch = Stopwatch()..start();
+    status.currentTest = test
+      ..lastKnownMessage = ''
+      ..timeoutTimer = createTimeoutTimer(test, status)
+      ..stopwatch = (Stopwatch()..start());
 
     // Reset the test specific output information (stdout, stderr) on the
     // browser, since a new test is being started.
@@ -1086,10 +1058,8 @@
     testingServer.underTermination = true;
     for (var status in browserStatus.values) {
       browsers.add(status.browser);
-      if (status.nextTestTimeout != null) {
-        status.nextTestTimeout.cancel();
-        status.nextTestTimeout = null;
-      }
+      status.nextTestTimeout?.cancel();
+      status.nextTestTimeout = null;
     }
 
     for (var browser in browsers) {
@@ -1117,7 +1087,7 @@
 
   final String localIp;
   final bool requiresFocus;
-  BrowserTestRunner testRunner;
+  late BrowserTestRunner testRunner;
 
   static const String driverPath = "/driver";
   static const String nextTestPath = "/next_test";
@@ -1128,13 +1098,13 @@
   static const String terminateSignal = "TERMINATE";
 
   var testCount = 0;
-  HttpServer errorReportingServer;
+  late HttpServer errorReportingServer;
   bool underTermination = false;
 
-  TestChangedCallback testDoneCallBack;
-  TestChangedCallback testStatusUpdateCallBack;
-  TestChangedCallback testStartedCallBack;
-  NextTestCallback nextTestCallBack;
+  late TestChangedCallback testDoneCallBack;
+  late TestChangedCallback testStatusUpdateCallBack;
+  late TestChangedCallback testStartedCallBack;
+  late NextTestCallback nextTestCallBack;
 
   BrowserTestingServer(this.configuration, this.localIp, this.requiresFocus);
 
@@ -1172,14 +1142,14 @@
   }
 
   void setupDispatchingServer(_) {
-    var server = configuration.servers.server;
+    var server = configuration.servers.server!;
     void noCache(HttpRequest request) {
       request.response.headers
           .set("Cache-Control", "no-cache, no-store, must-revalidate");
     }
 
     int testId(HttpRequest request) =>
-        int.parse(request.uri.queryParameters["id"]);
+        int.parse(request.uri.queryParameters["id"]!);
     String browserId(HttpRequest request, String prefix) =>
         request.uri.path.substring(prefix.length + 1);
 
@@ -1236,7 +1206,7 @@
   }
 
   void handleReport(HttpRequest request, String browserId, int testId,
-      {bool isStatusUpdate}) {
+      {required bool isStatusUpdate}) {
     var buffer = StringBuffer();
     request.cast<List<int>>().transform(utf8.decoder).listen((data) {
       buffer.write(data);
@@ -1281,18 +1251,11 @@
   }
 
   String getDriverUrl(String browserId) {
-    if (errorReportingServer == null) {
-      print("Bad browser testing server, you are not started yet. Can't "
-          "produce driver url");
-      exit(1);
-      // This should never happen - exit immediately;
-    }
-
     return "http://$localIp:${configuration.servers.port}/driver/$browserId";
   }
 
   Future<String> getDriverPage(String browserId) async {
-    await testRunner.browserStatus[browserId]?.browser?.onDriverPageRequested();
+    await testRunner.browserStatus[browserId]?.browser.onDriverPageRequested();
     var errorReportingUrl =
         "http://$localIp:${errorReportingServer.port}/$browserId";
     var driverContent = """
diff --git a/pkg/test_runner/lib/src/build_configurations.dart b/pkg/test_runner/lib/src/build_configurations.dart
index 2fd09f5..f684531 100644
--- a/pkg/test_runner/lib/src/build_configurations.dart
+++ b/pkg/test_runner/lib/src/build_configurations.dart
@@ -77,7 +77,6 @@
 }
 
 List<String> _selectBuildTargets(Configuration inner) {
-  final result = <String>[];
   final compiler = inner.compiler;
   const targetsForCompilers = {
     Compiler.dartk: ['runtime'],
@@ -89,7 +88,7 @@
     Compiler.dart2analyzer: ['create_sdk'],
     Compiler.specParser: <String>[],
   };
-  result.addAll(targetsForCompilers[compiler]);
+  final result = [...targetsForCompilers[compiler]!];
 
   if (compiler == Compiler.dartkp &&
       [Architecture.arm, Architecture.arm64, Architecture.arm_x64]
diff --git a/pkg/test_runner/lib/src/command.dart b/pkg/test_runner/lib/src/command.dart
index 7ba599f..8db8dfb 100644
--- a/pkg/test_runner/lib/src/command.dart
+++ b/pkg/test_runner/lib/src/command.dart
@@ -26,11 +26,11 @@
   int get maxNumRetries => 2;
 
   /// Reproduction command.
-  String get reproductionCommand => null;
+  String get reproductionCommand;
 
   /// We compute the Command.hashCode lazily and cache it here, since it might
   /// be expensive to compute (and hashCode is called often).
-  int _cachedHashCode;
+  int? _cachedHashCode;
 
   Command._(this.displayName, {this.index = 0});
 
@@ -52,7 +52,7 @@
       _buildHashCode(builder);
       _cachedHashCode = builder.value;
     }
-    return _cachedHashCode;
+    return _cachedHashCode!;
   }
 
   operator ==(Object other) =>
@@ -85,10 +85,12 @@
   final Map<String, String> environmentOverrides;
 
   /// Working directory for the command.
-  final String workingDirectory;
+  final String? workingDirectory;
 
   ProcessCommand(String displayName, this.executable, this.arguments,
-      [this.environmentOverrides, this.workingDirectory, int index = 0])
+      [this.environmentOverrides = const {},
+      this.workingDirectory,
+      int index = 0])
       : super._(displayName, index: index) {
     if (io.Platform.operatingSystem == 'windows') {
       // Windows can't handle the first command if it is a .bat file or the like
@@ -120,7 +122,7 @@
 
   String get reproductionCommand {
     var env = StringBuffer();
-    environmentOverrides?.forEach((key, value) =>
+    environmentOverrides.forEach((key, value) =>
         (io.Platform.operatingSystem == 'windows')
             ? env.write('set $key=${escapeCommandLineArgument(value)} & ')
             : env.write('$key=${escapeCommandLineArgument(value)} '));
@@ -162,10 +164,10 @@
       String executable,
       List<String> arguments,
       Map<String, String> environmentOverrides,
-      {bool alwaysCompile,
-      String workingDirectory,
+      {required bool alwaysCompile,
+      String? workingDirectory,
       int index = 0})
-      : _alwaysCompile = alwaysCompile ?? false,
+      : _alwaysCompile = alwaysCompile,
         super(displayName, executable, arguments, environmentOverrides,
             workingDirectory, index);
 
@@ -254,9 +256,9 @@
       String executable,
       List<String> arguments,
       Map<String, String> environmentOverrides,
-      {this.useSdk,
-      bool alwaysCompile,
-      String workingDirectory,
+      {required this.useSdk,
+      required bool alwaysCompile,
+      String? workingDirectory,
       int index = 0})
       : super("dart2js", outputFile, bootstrapDependencies, executable,
             arguments, environmentOverrides,
@@ -267,7 +269,7 @@
   @override
   CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
       List<int> stderr, Duration time, bool compilationSkipped,
-      [int pid = 0]) {
+      [int? pid = 0]) {
     return Dart2jsCompilerCommandOutput(
         this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
   }
@@ -309,9 +311,9 @@
       String executable,
       List<String> arguments,
       Map<String, String> environmentOverrides,
-      {this.compilerPath,
-      bool alwaysCompile,
-      String workingDirectory,
+      {required this.compilerPath,
+      required bool alwaysCompile,
+      String? workingDirectory,
       int index = 0})
       : super("dartdevc", outputFile, bootstrapDependencies, executable,
             arguments, environmentOverrides,
@@ -365,7 +367,7 @@
       String executable,
       List<String> arguments,
       Map<String, String> environmentOverrides,
-      String workingDirectory,
+      String? workingDirectory,
       {int index = 0})
       : super("fasta", outputFile, bootstrapDependencies, executable, arguments,
             environmentOverrides,
@@ -386,7 +388,7 @@
 
   FastaCommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
           List<int> stderr, Duration time, bool compilationSkipped,
-          [int pid = 0]) =>
+          [int? pid = 0]) =>
       FastaCommandOutput(
           this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
 
@@ -404,7 +406,7 @@
     String relativizeAndEscape(String argument) {
       if (workingDirectory != null) {
         argument = argument.replaceAll(
-            workingDirectory, Uri.directory(".").toFilePath());
+            workingDirectory!, Uri.directory(".").toFilePath());
       }
       return escapeCommandLineArgument(argument);
     }
@@ -412,10 +414,10 @@
     var buffer = StringBuffer();
     if (workingDirectory != null && !io.Platform.isWindows) {
       buffer.write("(cd ");
-      buffer.write(escapeCommandLineArgument(workingDirectory));
+      buffer.write(escapeCommandLineArgument(workingDirectory!));
       buffer.write(" ; ");
     }
-    environmentOverrides?.forEach((key, value) {
+    environmentOverrides.forEach((key, value) {
       if (io.Platform.isWindows) {
         buffer.write("set ");
       }
@@ -462,7 +464,7 @@
       String executable,
       List<String> arguments,
       Map<String, String> environmentOverrides,
-      {bool alwaysCompile,
+      {required bool alwaysCompile,
       int index = 0})
       : super('vm_compile_to_kernel', outputFile, bootstrapDependencies,
             executable, arguments, environmentOverrides,
@@ -480,7 +482,7 @@
           List<int> stderr,
           Duration time,
           bool compilationSkipped,
-          [int pid = 0]) =>
+          [int? pid = 0]) =>
       VMKernelCompilationCommandOutput(
           this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
 
@@ -547,7 +549,7 @@
 
   CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
           List<int> stderr, Duration time, bool compilationSkipped,
-          [int pid = 0]) =>
+          [int? pid = 0]) =>
       AnalysisCommandOutput(
           this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
 }
@@ -569,7 +571,7 @@
           List<int> stderr,
           Duration time,
           bool compilationSkipped,
-          [int pid = 0]) =>
+          [int? pid = 0]) =>
       CompareAnalyzerCfeCommandOutput(
           this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
 }
@@ -591,7 +593,7 @@
           List<int> stderr,
           Duration time,
           bool compilationSkipped,
-          [int pid = 0]) =>
+          [int? pid = 0]) =>
       SpecParseCommandOutput(
           this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
 }
@@ -618,9 +620,9 @@
 // must be in the harness.
 class RRCommand extends Command {
   VMCommand originalCommand;
-  VMCommand wrappedCommand;
-  io.Directory recordingDir;
-  io.Directory savedDir;
+  late VMCommand wrappedCommand;
+  late io.Directory recordingDir;
+  late io.Directory savedDir;
 
   RRCommand(this.originalCommand)
       : super._("rr", index: originalCommand.index) {
@@ -643,13 +645,16 @@
   RRCommand indexedCopy(int index) =>
       RRCommand(originalCommand.indexedCopy(index));
 
-  Future<CommandOutput> run(int timeout) async {
+  Future<CommandOutput> run(
+      int timeout, TestConfiguration configuration) async {
     // rr will fail if the output trace directory already exists. Delete any
     // that might be leftover from interrupting the harness.
     if (await recordingDir.exists()) {
       await recordingDir.delete(recursive: true);
     }
-    final output = await RunningProcess(wrappedCommand, timeout).run();
+    final output = await RunningProcess(wrappedCommand, timeout,
+            configuration: configuration)
+        .run();
     if (output.hasCrashed) {
       if (await savedDir.exists()) {
         await savedDir.delete(recursive: true);
@@ -739,6 +744,9 @@
 
   String toString() => 'Steps to push precompiled runner and precompiled code '
       'to an attached device. Uses (and requires) adb.';
+
+  @override
+  String get reproductionCommand => throw UnimplementedError();
 }
 
 class AdbDartkCommand extends Command implements AdbCommand {
@@ -790,12 +798,15 @@
 
   String toString() => 'Steps to push Dart VM and Dill file '
       'to an attached device. Uses (and requires) adb.';
+
+  @override
+  String get reproductionCommand => throw UnimplementedError();
 }
 
 class JSCommandLineCommand extends ProcessCommand {
   JSCommandLineCommand(
       String displayName, String executable, List<String> arguments,
-      [Map<String, String> environmentOverrides, int index = 0])
+      [Map<String, String> environmentOverrides = const {}, int index = 0])
       : super(displayName, executable, arguments, environmentOverrides, null,
             index);
 
@@ -809,7 +820,7 @@
           List<int> stderr,
           Duration time,
           bool compilationSkipped,
-          [int pid = 0]) =>
+          [int? pid = 0]) =>
       JSCommandLineOutput(this, exitCode, timedOut, stdout, stderr, time);
 }
 
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 03db24c..f90aba4 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -162,7 +162,7 @@
 
   BrowserTestJsonResult(this.outcome, this.htmlDom, this.events);
 
-  static BrowserTestJsonResult parseFromString(String content) {
+  static BrowserTestJsonResult? parseFromString(String content) {
     void validate(String message, bool isValid) {
       if (!isValid) {
         throw "InvalidFormat sent from browser driving page: $message:\n\n"
@@ -177,7 +177,9 @@
         // TODO(srawlins): This will promote `events` in null safety.
         var eventList = events as List<dynamic>;
 
-        var messagesByType = {for (var type in _allowedTypes) type: <String>[]};
+        var messagesByType = {
+          for (var type in _allowedTypes) type: <String?>[]
+        };
 
         for (var entry in eventList) {
           validate("Entry must be a Map", entry is Map);
@@ -198,12 +200,12 @@
             validate("'stack_trace' must be a String", stackTrace is String);
           }
 
-          messagesByType[type].add(value as String);
+          messagesByType[type]!.add(value as String?);
         }
         validate("The message must have exactly one 'dom' entry.",
-            messagesByType['dom'].length == 1);
+            messagesByType['dom']!.length == 1);
 
-        var dom = messagesByType['dom'][0];
+        var dom = messagesByType['dom']![0]!;
         if (dom.endsWith('\n')) {
           dom = '$dom\n';
         }
@@ -221,11 +223,11 @@
     return null;
   }
 
-  static Expectation _getOutcome(Map<String, List<String>> messagesByType) {
-    occurred(String type) => messagesByType[type].isNotEmpty;
+  static Expectation _getOutcome(Map<String, List<String?>> messagesByType) {
+    occurred(String type) => messagesByType[type]!.isNotEmpty;
 
     searchForMsg(List<String> types, String message) {
-      return types.any((type) => messagesByType[type].contains(message));
+      return types.any((type) => messagesByType[type]!.contains(message));
     }
 
     // FIXME(kustermann,ricow): I think this functionality doesn't work in
@@ -241,7 +243,7 @@
       return Expectation.runtimeError;
     }
 
-    if (messagesByType['dom'][0].contains('FAIL')) {
+    if (messagesByType['dom']![0]!.contains('FAIL')) {
       return Expectation.runtimeError;
     }
 
@@ -276,7 +278,7 @@
 
 class BrowserCommandOutput extends CommandOutput
     with _UnittestSuiteMessagesMixin {
-  final BrowserTestJsonResult _jsonResult;
+  final BrowserTestJsonResult? _jsonResult;
   final BrowserTestOutput _result;
   final Expectation _outcome;
 
@@ -319,8 +321,8 @@
         outcome,
         parsedResult,
         command.configuration.buildDirectory,
-        encodeUtf8(""),
-        encodeUtf8(stderr));
+        utf8.encode(""),
+        utf8.encode(stderr));
   }
 
   BrowserCommandOutput._internal(
@@ -394,16 +396,16 @@
 
     void _showError(String header, event) {
       output.subsection(header);
-      var value = event["value"] as String;
+      var value = event["value"] as String?;
       if (event["stack_trace"] != null) {
-        value = '$value\n${event["stack_trace"] as String}';
+        value = '$value\n${event["stack_trace"]}';
       }
       showedError = true;
       output.write(value);
 
       // Skip deobfuscation if there is no indication that there is a stack
       // trace in the string value.
-      if (!value.contains(RegExp('\\.js:'))) return;
+      if (!value!.contains(RegExp('\\.js:'))) return;
       var stringStack = value
           // Convert `http:` URIs to relative `file:` URIs.
           .replaceAll(RegExp('http://[^/]*/root_build/'), '$_buildDirectory/')
@@ -415,7 +417,7 @@
       _deobfuscateAndWriteStack(stringStack, output);
     }
 
-    for (var event in _jsonResult.events) {
+    for (var event in _jsonResult!.events) {
       if (event["type"] == "sync_exception") {
         _showError("Runtime error", event);
       } else if (event["type"] == "window_onerror") {
@@ -432,10 +434,10 @@
     }
 
     output.subsection("Events");
-    for (var event in _jsonResult.events) {
-      switch (event["type"] as String) {
+    for (var event in _jsonResult!.events) {
+      switch (event["type"] as String?) {
         case "debug":
-          output.write('- debug "${event["value"] as String}"');
+          output.write('- debug "${event["value"]}"');
           break;
 
         case "dom":
@@ -443,7 +445,7 @@
           break;
 
         case "print":
-          output.write('- print "${event["value"] as String}"');
+          output.write('- print "${event["value"]}"');
           break;
 
         case "window_onerror":
@@ -454,7 +456,8 @@
           break;
 
         default:
-          output.write("- ${prettifyJson(event)}");
+          output.write(
+              "- ${const JsonEncoder.withIndent('      ').convert(event)}");
       }
     }
   }
@@ -476,7 +479,7 @@
     for (var diagnostic in jsonData['diagnostics'] as List<dynamic>) {
       var diagnosticMap = diagnostic as Map<String, dynamic>;
 
-      var type = diagnosticMap['type'] as String;
+      var type = diagnosticMap['type'] as String?;
       var code = diagnosticMap['code'] as String;
       var errorCode = '$type.${code.toUpperCase()}';
 
@@ -484,7 +487,7 @@
           diagnosticMap, diagnosticMap['problemMessage'] as String, errorCode);
       result.add(error);
 
-      var contextMessages = diagnosticMap['contextMessages'] as List<dynamic>;
+      var contextMessages = diagnosticMap['contextMessages'] as List<dynamic>?;
       for (var contextMessage in contextMessages ?? const []) {
         var contextMessageMap = contextMessage as Map<String, dynamic>;
         error.contextMessages.add(
@@ -496,15 +499,15 @@
   }
 
   static AnalyzerError _parse(Map<String, dynamic> diagnostic, String message,
-      [String errorCode]) {
+      [String? errorCode]) {
     var location = diagnostic['location'] as Map<String, dynamic>;
 
     var range = location['range'] as Map<String, dynamic>;
     var start = range['start'] as Map<String, dynamic>;
     var end = range['end'] as Map<String, dynamic>;
     return AnalyzerError._(
-        severity: diagnostic['severity'] as String,
-        errorCode: errorCode,
+        severity: diagnostic['severity'] as String? ?? '',
+        errorCode: errorCode ?? '',
         file: location['file'] as String,
         message: message,
         line: start['line'] as int,
@@ -523,13 +526,13 @@
   final List<AnalyzerError> contextMessages = [];
 
   AnalyzerError._(
-      {this.severity,
-      this.errorCode,
-      this.file,
-      this.message,
-      this.line,
-      this.column,
-      this.length});
+      {this.severity = '',
+      this.errorCode = '',
+      required this.file,
+      required this.message,
+      required this.line,
+      required this.column,
+      required this.length});
 
   @override
   int compareTo(AnalyzerError other) {
@@ -549,7 +552,7 @@
   static void parseErrors(
     String stdout,
     List<StaticError> errors, [
-    List<StaticError> warnings,
+    List<StaticError>? warnings,
   ]) {
     StaticError convert(AnalyzerError error) {
       var staticError = StaticError(ErrorSource.analyzer, error.errorCode,
@@ -587,7 +590,7 @@
 
   /// If the stdout of analyzer could not be parsed as valid JSON, this will be
   /// the stdout as a string instead. Otherwise it will be null.
-  String get invalidJsonStdout {
+  String? get invalidJsonStdout {
     if (!_parsedErrors) {
       _parseErrors();
       _parsedErrors = true;
@@ -596,7 +599,7 @@
     return _invalidJsonStdout;
   }
 
-  String _invalidJsonStdout;
+  String? _invalidJsonStdout;
 
   AnalysisCommandOutput(
       Command command,
@@ -699,7 +702,7 @@
       super.describe(testCase, progress, output);
     } else {
       // Parse and sort the errors.
-      var errorsByFile = <String, List<AnalyzerError>>{};
+      var errorsByFile = <String?, List<AnalyzerError>>{};
       for (var error in AnalyzerError.parseStdout(decodeUtf8(stdout))) {
         errorsByFile.putIfAbsent(error.file, () => []).add(error);
       }
@@ -708,12 +711,12 @@
       files.sort();
 
       for (var file in files) {
-        var path = Path(file)
+        var path = Path(file!)
             .relativeTo(testCase.testFile.path.directoryPath)
             .toString();
         output.subsection("unexpected analysis errors in $path");
 
-        var errors = errorsByFile[file];
+        var errors = errorsByFile[file]!;
         errors.sort();
 
         for (var error in errors) {
@@ -1398,8 +1401,8 @@
   /// them to [errors] as coming from [errorSource].
   static void _parseCfeErrors(ErrorSource errorSource, RegExp regExp,
       String stdout, List<StaticError> errors,
-      [List<StaticError> warnings]) {
-    StaticError previousError;
+      [List<StaticError>? warnings]) {
+    StaticError? previousError;
     for (var match in regExp.allMatches(stdout)) {
       var line = _parseNullableInt(match.group(2));
       var column = _parseNullableInt(match.group(3));
@@ -1423,8 +1426,8 @@
       assert(column != null);
 
       var error = StaticError(
-          severity == "Context" ? ErrorSource.context : errorSource, message,
-          line: line, column: column);
+          severity == "Context" ? ErrorSource.context : errorSource, message!,
+          line: line, column: column!);
 
       if (severity == "Context") {
         // Attach context messages to the preceding error/warning.
@@ -1438,7 +1441,7 @@
         if (severity == "Error") {
           errors.add(error);
         } else {
-          warnings.add(error);
+          warnings!.add(error);
         }
         previousError = error;
       }
@@ -1446,7 +1449,7 @@
   }
 
   /// Same as `int.parse`, but allows nulls to simply pass through.
-  static int _parseNullableInt(String s) {
+  static int? _parseNullableInt(String? s) {
     if (s == null) {
       // ignore: avoid_returning_null
       return null;
@@ -1560,15 +1563,14 @@
   ///
   /// If [writer] is given, outputs a description of any error mismatches.
   Expectation _validateExpectedErrors(TestCase testCase,
-      [OutputWriter writer]) {
+      [OutputWriter? writer]) {
     // Filter out errors that aren't for this configuration.
     var errorSource = {
       Compiler.dart2analyzer: ErrorSource.analyzer,
       Compiler.dart2js: ErrorSource.web,
       Compiler.dartdevc: ErrorSource.web,
       Compiler.fasta: ErrorSource.cfe
-    }[testCase.configuration.compiler];
-    assert(errorSource != null);
+    }[testCase.configuration.compiler]!;
 
     var expected = testCase.testFile.expectedErrors
         .where((error) => error.source == errorSource);
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index e222ac8..7af6b8e 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -150,9 +150,7 @@
       /// Each test has its own temporary directory to avoid name collisions.
       String tempDir,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
-    return CommandArtifact([], null, null);
-  }
+      Map<String, String> environmentOverrides);
 
   List<String> computeCompilerArguments(
       TestFile testFile, List<String> vmOptions, List<String> args) {
@@ -169,8 +167,8 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
-    return [artifact.filename];
+      CommandArtifact? artifact) {
+    return artifact == null ? [] : [artifact.filename];
   }
 }
 
@@ -179,14 +177,15 @@
   NoneCompilerConfiguration(TestConfiguration configuration)
       : super._subclass(configuration);
 
-  bool get hasCompiler => false;
+  @override
+  final bool hasCompiler = false;
 
   List<String> computeRuntimeArguments(
       RuntimeConfiguration runtimeConfiguration,
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     return [
       if (_enableAsserts) '--enable_asserts',
       if (_configuration.hotReload)
@@ -202,6 +201,13 @@
       ...testFile.dartOptions
     ];
   }
+
+  @override
+  CommandArtifact computeCompilationArtifact(String tempDir,
+      List<String> arguments, Map<String, String> environmentOverrides) {
+    throw UnsupportedError(
+        '"None" compiler configuration has no compilation artifacts');
+  }
 }
 
 class VMKernelCompilerConfiguration extends CompilerConfiguration
@@ -251,8 +257,8 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
-    var filename = artifact.filename;
+      CommandArtifact? artifact) {
+    var filename = artifact!.filename;
     if (runtimeConfiguration is DartkAdbRuntimeConfiguration) {
       // On Android the Dill file will be pushed to a different directory on the
       // device. Use that one instead.
@@ -277,7 +283,7 @@
 }
 
 typedef CompilerArgumentsFunction = List<String> Function(
-    List<String> globalArguments, String previousCompilerOutput);
+    List<String> globalArguments, String? previousCompilerOutput);
 
 class PipelineCommand {
   final CompilerConfiguration compilerConfiguration;
@@ -287,8 +293,7 @@
 
   factory PipelineCommand.runWithGlobalArguments(
       CompilerConfiguration configuration) {
-    return PipelineCommand._(configuration,
-        (List<String> globalArguments, String previousOutput) {
+    return PipelineCommand._(configuration, (globalArguments, previousOutput) {
       assert(previousOutput == null);
       return globalArguments;
     });
@@ -297,7 +302,7 @@
   factory PipelineCommand.runWithDartOrKernelFile(
       CompilerConfiguration configuration) {
     return PipelineCommand._(configuration,
-        (List<String> globalArguments, String previousOutput) {
+        (List<String> globalArguments, String? previousOutput) {
       var filtered = globalArguments
           .where((name) => name.endsWith('.dart') || name.endsWith('.dill'))
           .toList();
@@ -309,14 +314,14 @@
   factory PipelineCommand.runWithPreviousKernelOutput(
       CompilerConfiguration configuration) {
     return PipelineCommand._(configuration,
-        (List<String> globalArguments, String previousOutput) {
-      assert(previousOutput.endsWith('.dill'));
-      return _replaceDartFiles(globalArguments, previousOutput);
+        (List<String> globalArguments, String? previousOutput) {
+      assert(previousOutput!.endsWith('.dill'));
+      return _replaceDartFiles(globalArguments, previousOutput!);
     });
   }
 
   List<String> extractArguments(
-      List<String> globalArguments, String previousOutput) {
+      List<String> globalArguments, String? previousOutput) {
     return _argumentsFunction(globalArguments, previousOutput);
   }
 }
@@ -374,7 +379,7 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     var lastCompilerConfiguration = pipelineCommands.last.compilerConfiguration;
     return lastCompilerConfiguration.computeRuntimeArguments(
         runtimeConfiguration, testFile, vmOptions, originalArguments, artifact);
@@ -459,13 +464,12 @@
     var out = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
     var babel = _configuration.babel;
     var babelOut = out;
-    if (babel != null && babel.isNotEmpty) {
+    if (babel.isNotEmpty) {
       out = out.replaceAll('.js', '.raw.js');
     }
     var commands = [
       computeCompilationCommand(out, compilerArguments, environmentOverrides),
-      if (babel != null && babel.isNotEmpty)
-        computeBabelCommand(out, babelOut, babel)
+      if (babel.isNotEmpty) computeBabelCommand(out, babelOut, babel)
     ];
 
     return CommandArtifact(commands, babelOut, 'application/javascript');
@@ -476,13 +480,13 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     var sdk = _useSdk
         ? Uri.directory(_configuration.buildDirectory).resolve('dart-sdk/')
         : Uri.directory(Repository.dir.toNativePath()).resolve('sdk/');
     var preambleDir = sdk.resolve('lib/_internal/js_runtime/lib/preambles/');
     return runtimeConfiguration.dart2jsPreambles(preambleDir)
-      ..add(artifact.filename);
+      ..add(artifact!.filename);
   }
 
   Command computeBabelCommand(String input, String output, String options) {
@@ -568,13 +572,13 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     return [
       '--experimental-wasm-gc',
       '--wasm-gc-js-interop',
       'pkg/dart2wasm/bin/run_wasm.js',
       '--',
-      artifact.filename,
+      artifact!.filename,
     ];
   }
 }
@@ -670,7 +674,7 @@
         : Repository.uri.resolve('pkg/dev_compiler/bin/dartdevc.dart').path;
     return DevCompilerCompilationCommand(outputFile, bootstrapDependencies(),
         computeCompilerPath(), args, environment,
-        compilerPath: compilerPath);
+        compilerPath: compilerPath, alwaysCompile: false);
   }
 
   CommandArtifact computeCompilationArtifact(String tempDir,
@@ -749,13 +753,13 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     var sdkDir = _useSdk
         ? Uri.directory(_configuration.buildDirectory).resolve('dart-sdk/')
         : Uri.directory(Repository.dir.toNativePath()).resolve('sdk/');
     var preambleDir = sdkDir.resolve('lib/_internal/js_runtime/lib/preambles/');
     return runtimeConfiguration.dart2jsPreambles(preambleDir)
-      ..add(artifact.filename);
+      ..add(artifact!.filename);
   }
 }
 
@@ -927,7 +931,7 @@
     ];
 
     return CompilationCommand('precompiler', tempDir, bootstrapDependencies(),
-        exec, args, environmentOverrides,
+        exec!, args, environmentOverrides,
         alwaysCompile: !_useSdk);
   }
 
@@ -948,12 +952,12 @@
   }
 
   static const String ndkPath = "third_party/android_tools/ndk";
-  String get abiTriple => _isArm || _isArmX64
+  String? get abiTriple => _isArm || _isArmX64
       ? "arm-linux-androideabi"
       : _isArm64
           ? "aarch64-linux-android"
           : null;
-  String get host => Platform.isLinux
+  String? get host => Platform.isLinux
       ? "linux"
       : Platform.isMacOS
           ? "darwin"
@@ -961,8 +965,9 @@
 
   Command computeAssembleCommand(String tempDir, List arguments,
       Map<String, String> environmentOverrides) {
-    String cc, shared, ldFlags;
-    List<String> target;
+    late String cc;
+    String? shared, ldFlags;
+    List<String>? target;
     if (_isAndroid) {
       cc = "$ndkPath/toolchains/$abiTriple-4.9/prebuilt/"
           "$host-x86_64/bin/$abiTriple-gcc";
@@ -993,7 +998,7 @@
       throw "Platform not supported: ${Platform.operatingSystem}";
     }
 
-    String ccFlags;
+    String? ccFlags;
     switch (_configuration.architecture) {
       case Architecture.x64:
       case Architecture.x64c:
@@ -1087,8 +1092,8 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
-    var dir = artifact.filename;
+      CommandArtifact? artifact) {
+    var dir = artifact!.filename;
     if (runtimeConfiguration is DartPrecompiledAdbRuntimeConfiguration) {
       // On android the precompiled snapshot will be pushed to a different
       // directory on the device, use that one instead.
@@ -1162,7 +1167,7 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     return [
       if (_enableAsserts) '--enable_asserts',
       ...vmOptions,
@@ -1170,7 +1175,7 @@
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
-      ..._replaceDartFiles(originalArguments, artifact.filename),
+      ..._replaceDartFiles(originalArguments, artifact!.filename),
       ...testFile.dartOptions
     ];
   }
@@ -1205,8 +1210,8 @@
     // Since this is not a real compilation, no artifacts are produced.
     return CommandArtifact(
         [AnalysisCommand(computeCompilerPath(), args, environmentOverrides)],
-        null,
-        null);
+        args.singleWhere((arg) => arg.endsWith('.dart')),
+        'application/vnd.dart');
   }
 
   List<String> computeRuntimeArguments(
@@ -1214,7 +1219,7 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     return [];
   }
 }
@@ -1240,7 +1245,8 @@
     return CommandArtifact([
       CompareAnalyzerCfeCommand(
           computeCompilerPath(), arguments.toList(), environmentOverrides)
-    ], null, null);
+    ], arguments.singleWhere((argument) => argument.endsWith('.dart')),
+        'application/vnd.dart');
   }
 
   List<String> computeRuntimeArguments(
@@ -1248,7 +1254,7 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     return [];
   }
 }
@@ -1262,12 +1268,11 @@
 
   CommandArtifact computeCompilationArtifact(String tempDir,
       List<String> arguments, Map<String, String> environmentOverrides) {
-    arguments = arguments.toList();
-
     // Since this is not a real compilation, no artifacts are produced.
     return CommandArtifact([
       SpecParseCommand(computeCompilerPath(), arguments, environmentOverrides)
-    ], null, null);
+    ], arguments.singleWhere((argument) => argument.endsWith('.dart')),
+        'application/vnd.dart');
   }
 
   List<String> computeRuntimeArguments(
@@ -1275,7 +1280,7 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     return [];
   }
 }
@@ -1434,7 +1439,7 @@
       TestFile testFile,
       List<String> vmOptions,
       List<String> originalArguments,
-      CommandArtifact artifact) {
+      CommandArtifact? artifact) {
     if (runtimeConfiguration is! NoneRuntimeConfiguration) {
       throw "--compiler=fasta only supports --runtime=none";
     }
diff --git a/pkg/test_runner/lib/src/configuration.dart b/pkg/test_runner/lib/src/configuration.dart
index e496f94..e9bf880 100644
--- a/pkg/test_runner/lib/src/configuration.dart
+++ b/pkg/test_runner/lib/src/configuration.dart
@@ -6,6 +6,7 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:smith/configuration.dart';
 import 'package:smith/smith.dart';
 
 import 'compiler_configuration.dart';
@@ -24,28 +25,28 @@
 /// executed on, etc.
 class TestConfiguration {
   TestConfiguration(
-      {this.configuration,
-      this.progress,
-      this.selectors,
-      this.build,
-      this.testList,
-      this.repeat,
-      this.batch,
-      this.copyCoreDumps,
-      this.rr,
-      this.isVerbose,
-      this.listTests,
-      this.listStatusFiles,
-      this.cleanExit,
-      this.silentFailures,
-      this.printTiming,
-      this.printReport,
-      this.reportFailures,
-      this.reportInJson,
-      this.resetBrowser,
-      this.writeDebugLog,
-      this.writeResults,
-      this.writeLogs,
+      {required this.configuration,
+      this.progress = Progress.compact,
+      this.selectors = const {},
+      this.build = false,
+      this.testList = const [],
+      this.repeat = 1,
+      this.batch = false,
+      this.copyCoreDumps = false,
+      this.rr = false,
+      this.isVerbose = false,
+      this.listTests = false,
+      this.listStatusFiles = false,
+      this.cleanExit = false,
+      this.silentFailures = false,
+      this.printTiming = false,
+      this.printReport = false,
+      this.reportFailures = false,
+      this.reportInJson = false,
+      this.resetBrowser = false,
+      this.writeDebugLog = false,
+      this.writeResults = false,
+      this.writeLogs = false,
       this.drtPath,
       this.chromePath,
       this.safariPath,
@@ -53,26 +54,29 @@
       this.dartPath,
       this.dartPrecompiledPath,
       this.genSnapshotPath,
-      this.taskCount,
-      this.shardCount,
-      this.shard,
+      this.taskCount = 1,
+      this.shardCount = 1,
+      this.shard = 1,
       this.stepName,
-      this.testServerPort,
-      this.testServerCrossOriginPort,
-      this.testDriverErrorPort,
-      this.localIP,
-      this.keepGeneratedFiles,
-      this.sharedOptions,
-      String packages,
+      this.testServerPort = 0,
+      this.testServerCrossOriginPort = 0,
+      this.testDriverErrorPort = 0,
+      this.localIP = '0.0.0.0',
+      this.keepGeneratedFiles = false,
+      this.sharedOptions = const [],
+      String? packages,
       this.serviceResponseSizesDirectory,
       this.suiteDirectory,
-      this.outputDirectory,
-      this.reproducingArguments,
-      this.fastTestsOnly,
-      this.printPassingStdout})
-      : _packages = packages;
+      required this.outputDirectory,
+      required this.reproducingArguments,
+      this.fastTestsOnly = false,
+      this.printPassingStdout = false})
+      : packages = packages ??
+            Repository.uri
+                .resolve('.dart_tool/package_config.json')
+                .toFilePath();
 
-  final Map<String, RegExp> selectors;
+  final Map<String, RegExp?> selectors;
   final Progress progress;
   // The test configuration read from the -n option and the test matrix
   // or else computed from the test options.
@@ -124,20 +128,20 @@
 
   // Various file paths.
 
-  final String drtPath;
-  final String chromePath;
-  final String safariPath;
-  final String firefoxPath;
-  final String dartPath;
-  final String dartPrecompiledPath;
-  final String genSnapshotPath;
-  final List<String> testList;
+  final String? drtPath;
+  final String? chromePath;
+  final String? safariPath;
+  final String? firefoxPath;
+  final String? dartPath;
+  final String? dartPrecompiledPath;
+  final String? genSnapshotPath;
+  final List<String>? testList;
 
   final int taskCount;
   final int shardCount;
   final int shard;
   final int repeat;
-  final String stepName;
+  final String? stepName;
 
   final int testServerPort;
   final int testServerCrossOriginPort;
@@ -168,30 +172,19 @@
   /// Extra general options passed to the testing script.
   final List<String> sharedOptions;
 
-  String _packages;
+  final String packages;
 
-  String get packages {
-    // If the package config file path wasn't given, find it.
-    _packages ??=
-        Repository.uri.resolve('.dart_tool/package_config.json').toFilePath();
-
-    return _packages;
-  }
-
-  final String serviceResponseSizesDirectory;
+  final String? serviceResponseSizesDirectory;
   final String outputDirectory;
-  final String suiteDirectory;
+  final String? suiteDirectory;
   String get babel => configuration.babel;
   String get builderTag => configuration.builderTag;
   final List<String> reproducingArguments;
 
-  TestingServers _servers;
+  TestingServers? _servers;
 
   TestingServers get servers {
-    if (_servers == null) {
-      throw StateError("Servers have not been started yet.");
-    }
-    return _servers;
+    return _servers ?? (throw StateError("Servers have not been started yet."));
   }
 
   /// Returns true if this configuration uses the new front end (fasta)
@@ -212,7 +205,7 @@
   /// The base directory named for this configuration, like:
   ///
   ///     ReleaseX64
-  String _configurationDirectory;
+  String? _configurationDirectory;
 
   String get configurationDirectory {
     // Lazy initialize and cache since it requires hitting the file system.
@@ -224,7 +217,7 @@
   ///     build/ReleaseX64
   String get buildDirectory => system.outputDirectory + configurationDirectory;
 
-  int _timeout;
+  int? _timeout;
 
   // TODO(whesse): Put non-default timeouts explicitly in configs, not this.
   /// Calculates a default timeout based on the compiler and runtime used,
@@ -247,7 +240,7 @@
       }
     }
 
-    return _timeout;
+    return _timeout!;
   }
 
   List<String> get standardOptions {
@@ -263,34 +256,28 @@
     return args;
   }
 
-  String _windowsSdkPath;
-
-  String get windowsSdkPath {
+  late final String? windowsSdkPath = () {
     if (!Platform.isWindows) {
       throw StateError(
           "Should not use windowsSdkPath when not running on Windows.");
     }
 
-    if (_windowsSdkPath == null) {
-      // When running tests on Windows, use cdb from depot_tools to dump
-      // stack traces of tests timing out.
-      try {
-        var path = Path("build/win_toolchain.json").toNativePath();
-        var text = File(path).readAsStringSync();
-        _windowsSdkPath = jsonDecode(text)['win_sdk'] as String;
-      } on dynamic {
-        // Ignore errors here. If win_sdk is not found, stack trace dumping
-        // for timeouts won't work.
-      }
+    // When running tests on Windows, use cdb from depot_tools to dump
+    // stack traces of tests timing out.
+    try {
+      var path = Path("build/win_toolchain.json").toNativePath();
+      var text = File(path).readAsStringSync();
+      return jsonDecode(text)['win_sdk'] as String;
+    } catch (_) {
+      // Ignore errors here. If win_sdk is not found, stack trace dumping
+      // for timeouts won't work.
     }
-
-    return _windowsSdkPath;
-  }
+  }();
 
   /// Gets the local file path to the browser executable for this configuration.
-  String get browserLocation {
+  late final String browserLocation = () {
     // If the user has explicitly configured a browser path, use it.
-    String location;
+    String? location;
     switch (runtime) {
       case Runtime.chrome:
         location = chromePath;
@@ -326,51 +313,36 @@
       }
     };
 
-    location = locations[runtime][System.find(Platform.operatingSystem)];
+    location = locations[runtime]![System.find(Platform.operatingSystem)];
 
     if (location == null) {
       throw "${runtime.name} is not supported on ${Platform.operatingSystem}";
     }
 
     return location;
-  }
+  }();
 
-  RuntimeConfiguration _runtimeConfiguration;
+  RuntimeConfiguration? _runtimeConfiguration;
 
   RuntimeConfiguration get runtimeConfiguration =>
       _runtimeConfiguration ??= RuntimeConfiguration(this);
 
-  CompilerConfiguration _compilerConfiguration;
+  CompilerConfiguration? _compilerConfiguration;
 
   CompilerConfiguration get compilerConfiguration =>
       _compilerConfiguration ??= CompilerConfiguration(this);
 
-  Set<Feature> _supportedFeatures;
-
   /// The set of [Feature]s supported by this configuration.
-  Set<Feature> get supportedFeatures {
-    if (_supportedFeatures != null) return _supportedFeatures;
-
-    _supportedFeatures = {};
-    switch (nnbdMode) {
-      case NnbdMode.legacy:
-        _supportedFeatures.add(Feature.nnbdLegacy);
-        break;
-      case NnbdMode.weak:
-        _supportedFeatures.add(Feature.nnbd);
-        _supportedFeatures.add(Feature.nnbdWeak);
-        break;
-      case NnbdMode.strong:
-        _supportedFeatures.add(Feature.nnbd);
-        _supportedFeatures.add(Feature.nnbdStrong);
-        break;
-    }
-
+  late final Set<Feature> supportedFeatures = {
     // TODO(rnystrom): Define more features for things like "dart:io", separate
     // int/double representation, etc.
-
-    return _supportedFeatures;
-  }
+    if (NnbdMode.legacy == configuration.nnbdMode)
+      Feature.nnbdLegacy
+    else
+      Feature.nnbd,
+    if (NnbdMode.weak == configuration.nnbdMode) Feature.nnbdWeak,
+    if (NnbdMode.strong == configuration.nnbdMode) Feature.nnbdStrong,
+  };
 
   /// Determines if this configuration has a compatible compiler and runtime
   /// and other valid fields.
@@ -441,7 +413,7 @@
   }
 
   void stopServers() {
-    if (_servers != null) _servers.stopServers();
+    _servers?.stopServers();
   }
 
   /// Returns the correct configuration directory (the last component of the
diff --git a/pkg/test_runner/lib/src/dependency_graph.dart b/pkg/test_runner/lib/src/dependency_graph.dart
index 4a60a62..8ebd94e 100644
--- a/pkg/test_runner/lib/src/dependency_graph.dart
+++ b/pkg/test_runner/lib/src/dependency_graph.dart
@@ -79,8 +79,8 @@
 
     _emitEvent(_addedController, node);
 
-    _stateCounts.putIfAbsent(node.state, () => 0);
-    _stateCounts[node.state] += 1;
+    _stateCounts[node.state] =
+        _stateCounts.putIfAbsent(node.state, () => 0) + 1;
 
     return node;
   }
@@ -90,9 +90,9 @@
     var fromState = node.state;
     node._state = state;
 
-    _stateCounts[fromState] -= 1;
+    _stateCounts[fromState] = _stateCounts[fromState]! - 1;
     _stateCounts.putIfAbsent(state, () => 0);
-    _stateCounts[state] += 1;
+    _stateCounts[state] = _stateCounts[state]! + 1;
 
     _emitEvent(_changedController, StateChangedEvent(node, fromState, state));
   }
diff --git a/pkg/test_runner/lib/src/environment.dart b/pkg/test_runner/lib/src/environment.dart
index 4d90271..303f30c 100644
--- a/pkg/test_runner/lib/src/environment.dart
+++ b/pkg/test_runner/lib/src/environment.dart
@@ -16,7 +16,7 @@
   "analyzer_use_fasta_parser": _Variable.bool((c) => c.useAnalyzerFastaParser),
   "arch": _Variable((c) => c.architecture.name, Architecture.names),
   "browser": _Variable.bool((c) => c.runtime.isBrowser),
-  "builder_tag": _Variable((c) => c.builderTag ?? "", const []),
+  "builder_tag": _Variable((c) => c.builderTag, const []),
   "checked": _Variable.bool((c) => c.isChecked),
   "compiler": _Variable((c) => c.compiler.name, Compiler.names),
   "csp": _Variable.bool((c) => c.isCsp),
diff --git a/pkg/test_runner/lib/src/expectation_set.dart b/pkg/test_runner/lib/src/expectation_set.dart
index 94ca4ef..ef125a1 100644
--- a/pkg/test_runner/lib/src/expectation_set.dart
+++ b/pkg/test_runner/lib/src/expectation_set.dart
@@ -135,14 +135,12 @@
     var part = parts[index];
 
     // Look for a non-glob child directory.
-    if (stringChildren.containsKey(part)) {
-      stringChildren[part].walk(parts, index + 1, result);
-    }
+    stringChildren[part]?.walk(parts, index + 1, result);
 
     // Look for any matching glob directories.
-    for (var regExp in regExpChildren.keys) {
-      if (regExp.hasMatch(part)) {
-        regExpChildren[regExp].walk(parts, index + 1, result);
+    for (var child in regExpChildren.entries) {
+      if (child.key.hasMatch(part)) {
+        child.value.walk(parts, index + 1, result);
       }
     }
   }
diff --git a/pkg/test_runner/lib/src/fuchsia.dart b/pkg/test_runner/lib/src/fuchsia.dart
index aeeab96..f3c8fc9 100644
--- a/pkg/test_runner/lib/src/fuchsia.dart
+++ b/pkg/test_runner/lib/src/fuchsia.dart
@@ -24,18 +24,18 @@
       RegExp(r'([0-9]+) .* qemu-system-x86');
   static final String serverReadyPattern = '[pm serve] serving';
 
-  static FuchsiaEmulator _inst;
+  static FuchsiaEmulator? _inst;
 
-  Process _emu;
-  Process _server;
-  String _deviceName;
+  Process? _emu;
+  Process? _server;
+  late String _deviceName;
 
   static Future<void> publishPackage(String buildDir, String mode) async {
     if (_inst == null) {
       _inst = FuchsiaEmulator();
-      await _inst._start();
+      await _inst!._start();
     }
-    await _inst._publishPackage(buildDir, mode);
+    await _inst!._publishPackage(buildDir, mode);
   }
 
   static void stop() {
@@ -43,7 +43,7 @@
   }
 
   static List<String> getTestArgs(String mode, List<String> arguments) {
-    return _inst._getSshArgs(
+    return _inst!._getSshArgs(
         mode,
         arguments.map((arg) =>
             arg.replaceAll(Repository.uri.toFilePath(), '/pkg/data/')));
@@ -59,7 +59,7 @@
     var deviceNameFuture = Completer<String>();
     var emuStdout = StringBuffer();
     var emuStderr = StringBuffer();
-    _emu.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen(
+    _emu!.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen(
         (String line) {
       if (!deviceNameFuture.isCompleted) {
         emuStdout.write(line);
@@ -77,7 +77,7 @@
       }
       _stop();
     });
-    _emu.stderr
+    _emu!.stderr
         .transform(utf8.decoder)
         .transform(const LineSplitter())
         .listen((String line) {
@@ -101,10 +101,10 @@
     ]);
 
     // Wait until the server is ready to serve packages.
-    var serverReadyFuture = Completer<String>();
+    var serverReadyFuture = Completer<void>();
     var serverStdout = StringBuffer();
     var serverStderr = StringBuffer();
-    _server.stdout
+    _server!.stdout
         .transform(utf8.decoder)
         .transform(const LineSplitter())
         .listen((String line) {
@@ -124,7 +124,7 @@
       }
       _stop();
     });
-    _server.stderr
+    _server!.stderr
         .transform(utf8.decoder)
         .transform(const LineSplitter())
         .listen((String line) {
@@ -177,7 +177,7 @@
   void _stop() {
     if (_emu != null) {
       DebugLogger.info('Stopping Fuchsia emulator');
-      _emu.kill(ProcessSignal.sigint);
+      _emu!.kill(ProcessSignal.sigint);
       _emu = null;
 
       // Killing femu.sh seems to leave the underlying emulator running. So
@@ -197,7 +197,7 @@
 
     if (_server != null) {
       DebugLogger.info('Stopping Fuchsia package server');
-      _server.kill();
+      _server!.kill();
       _server = null;
 
       // fserve.sh starts a package manager process in the background. We need
diff --git a/pkg/test_runner/lib/src/multitest.dart b/pkg/test_runner/lib/src/multitest.dart
index f6b5a87..0cebbc8 100644
--- a/pkg/test_runner/lib/src/multitest.dart
+++ b/pkg/test_runner/lib/src/multitest.dart
@@ -106,16 +106,16 @@
     var annotation = Annotation.tryParse(line);
     if (annotation != null) {
       testsAsLines.putIfAbsent(
-          annotation.key, () => List<String>.from(testsAsLines["none"]));
+          annotation.key, () => List<String>.from(testsAsLines["none"]!));
       // Add line to test with annotation.key as key, empty line to the rest.
-      for (var key in testsAsLines.keys) {
-        testsAsLines[key].add(annotation.key == key ? line : "");
+      for (var entry in testsAsLines.entries) {
+        entry.value.add(annotation.key == entry.key ? line : "");
       }
       outcomes.putIfAbsent(annotation.key, () => <String>{});
       if (annotation.rest != 'continued') {
         for (var nextOutcome in annotation.outcomes) {
           if (_multitestOutcomes.contains(nextOutcome)) {
-            outcomes[annotation.key].add(nextOutcome);
+            outcomes[annotation.key]!.add(nextOutcome);
           } else {
             DebugLogger.warning(
                 "${filePath.toNativePath()}: Invalid expectation "
@@ -140,9 +140,8 @@
   }
 
   // Check that every test (other than the none case) has at least one outcome.
-  var invalidTests = outcomes.keys
-      .where((test) => test != 'none' && outcomes[test].isEmpty)
-      .toList();
+  var invalidTests =
+      outcomes.keys.where((test) => test != 'none' && outcomes[test]!.isEmpty);
   for (var test in invalidTests) {
     DebugLogger.warning(
         "${filePath.toNativePath()}: Test $test has no valid expectation. "
@@ -153,8 +152,8 @@
   }
 
   // Copy all the tests into the output map tests, as multiline strings.
-  for (var key in testsAsLines.keys) {
-    tests[key] = testsAsLines[key].join(lineSeparator);
+  for (var entry in testsAsLines.entries) {
+    tests[entry.key] = entry.value.join(lineSeparator);
   }
 }
 
@@ -174,7 +173,6 @@
 
   var sourceDir = multitest.path.directoryPath;
   var targetDir = _createMultitestDirectory(outputDir, suiteDir, sourceDir);
-  assert(targetDir != null);
 
   // Copy all the relative imports of the multitest.
   var importsToCopy = _findAllRelativeImports(multitest.path);
@@ -196,11 +194,11 @@
   var baseFilename = multitest.path.filenameWithoutExtension;
 
   var testFiles = <TestFile>[];
-  for (var test in tests.keys) {
-    var sectionFilePath = targetDir.append('${baseFilename}_$test.dart');
-    _writeFile(sectionFilePath.toNativePath(), tests[test]);
+  for (var test in tests.entries) {
+    var sectionFilePath = targetDir.append('${baseFilename}_${test.key}.dart');
+    _writeFile(sectionFilePath.toNativePath(), test.value);
 
-    var outcome = outcomes[test];
+    var outcome = outcomes[test.key]!;
     var hasStaticWarning = outcome.contains('static type warning');
     var hasRuntimeError = outcome.contains('runtime error');
     var hasSyntaxError = outcome.contains('syntax error');
@@ -214,7 +212,7 @@
     }
 
     // Create a [TestFile] for each split out section test.
-    testFiles.add(multitest.split(sectionFilePath, test, tests[test],
+    testFiles.add(multitest.split(sectionFilePath, test.key, test.value,
         hasSyntaxError: hasSyntaxError,
         hasCompileError: hasCompileError,
         hasRuntimeError: hasRuntimeError,
@@ -243,7 +241,7 @@
 class Annotation {
   /// Parses the annotation in [line] or returns `null` if the line isn't a
   /// multitest annotation.
-  static Annotation tryParse(String line) {
+  static Annotation? tryParse(String line) {
     // Do an early return with "null" if this is not a valid multitest
     // annotation.
     if (!line.contains(multitestMarker)) return null;
@@ -290,7 +288,7 @@
     for (var line in file.readAsLinesSync()) {
       var match = relativeImportRegExp.firstMatch(line);
       if (match == null) continue;
-      var relativePath = match.group(3);
+      var relativePath = match.group(3)!;
 
       // If a multitest deliberately imports a non-existent file, don't try to
       // include it.
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 8b0b87d..41d6c63 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -33,12 +33,12 @@
 
 extension _IntOption on ArgParser {
   void addIntegerOption(String name,
-      {String abbr,
-      String help,
-      String valueHelp,
-      Iterable<String> allowed,
-      Map<String, String> allowedHelp,
-      String defaultsTo,
+      {String? abbr,
+      String? help,
+      String? valueHelp,
+      Iterable<String>? allowed,
+      Map<String, String>? allowedHelp,
+      String? defaultsTo,
       bool mandatory = false,
       bool hide = false,
       List<String> aliases = const []}) {
@@ -448,7 +448,7 @@
   /// encountering the first non-option string, the rest of the arguments are
   /// stored in the returned Map under the 'rest' key.
   List<TestConfiguration> parse(List<String> arguments) {
-    ArgResults results;
+    late ArgResults results;
     try {
       results = parser.parse(arguments);
     } on FormatException catch (error) {
@@ -614,7 +614,7 @@
   /// Recursively expands a configuration with multiple values per key into a
   /// list of configurations with exactly one value per key.
   List<TestConfiguration> _expandConfigurations(
-      Map<String, dynamic> data, Map<String, RegExp> selectors) {
+      Map<String, dynamic> data, Map<String, RegExp?> selectors) {
     var result = <TestConfiguration>[];
 
     // Handles a string option containing a space-separated list of words.
@@ -631,7 +631,7 @@
     var dart2jsOptions = listOption("dart2js-options");
     var vmOptions = listOption("vm-options");
     var sharedOptions = listOption("shared-options");
-    var experiments = data["enable-experiment"] as List<String>;
+    var experiments = data["enable-experiment"] as List<String>?;
 
     // JSON reporting implies listing and reporting.
     if (data['report-in-json'] as bool) {
@@ -642,7 +642,7 @@
     // Use verbose progress indication for verbose output unless buildbot
     // progress indication is requested.
     if ((data['verbose'] as bool) &&
-        (data['progress'] as String) != 'buildbot') {
+        (data['progress'] as String?) != 'buildbot') {
       data['progress'] = 'verbose';
     }
 
@@ -672,13 +672,13 @@
     var nnbdMode = NnbdMode.find(data["nnbd"] as String);
 
     void addConfiguration(Configuration innerConfiguration,
-        [String namedConfiguration]) {
+        [String? namedConfiguration]) {
       var configuration = TestConfiguration(
           configuration: innerConfiguration,
           progress: progress,
           selectors: selectors,
           build: data["build"] as bool,
-          testList: data["test-list-contents"] as List<String>,
+          testList: data["test-list-contents"] as List<String>?,
           repeat: int.parse(data["repeat"] as String),
           batch: !(data["no-batch"] as bool),
           copyCoreDumps: data["copy-coredumps"] as bool,
@@ -696,18 +696,18 @@
           writeDebugLog: data["write-debug-log"] as bool,
           writeResults: data["write-results"] as bool,
           writeLogs: data["write-logs"] as bool,
-          drtPath: data["drt"] as String,
-          chromePath: data["chrome"] as String,
-          safariPath: data["safari"] as String,
-          firefoxPath: data["firefox"] as String,
-          dartPath: data["dart"] as String,
-          dartPrecompiledPath: data["dart-precompiled"] as String,
-          genSnapshotPath: data["gen-snapshot"] as String,
+          drtPath: data["drt"] as String?,
+          chromePath: data["chrome"] as String?,
+          safariPath: data["safari"] as String?,
+          firefoxPath: data["firefox"] as String?,
+          dartPath: data["dart"] as String?,
+          dartPrecompiledPath: data["dart-precompiled"] as String?,
+          genSnapshotPath: data["gen-snapshot"] as String?,
           keepGeneratedFiles: data["keep-generated-files"] as bool,
           taskCount: int.parse(data["tasks"] as String),
           shardCount: int.parse(data["shards"] as String),
           shard: int.parse(data["shard"] as String),
-          stepName: data["step-name"] as String,
+          stepName: data["step-name"] as String?,
           testServerPort: int.parse(data['test-server-port'] as String),
           testServerCrossOriginPort:
               int.parse(data['test-server-cross-origin-port'] as String),
@@ -718,10 +718,10 @@
             ...sharedOptions,
             "-Dtest_runner.configuration=${innerConfiguration.name}"
           ],
-          packages: data["packages"] as String,
+          packages: data["packages"] as String?,
           serviceResponseSizesDirectory:
-              data['service-response-sizes-directory'] as String,
-          suiteDirectory: data["suite-dir"] as String,
+              data['service-response-sizes-directory'] as String?,
+          suiteDirectory: data["suite-dir"] as String?,
           outputDirectory: data["output-directory"] as String,
           reproducingArguments:
               _reproducingCommand(data, namedConfiguration != null),
@@ -739,10 +739,11 @@
     if (namedConfigurations.isNotEmpty) {
       var testMatrix = TestMatrix.fromPath(_testMatrixFile);
       for (var namedConfiguration in namedConfigurations) {
-        var configuration = testMatrix.configurations.singleWhere(
-            (c) => c.name == namedConfiguration,
-            orElse: () => null);
-        if (configuration == null) {
+        try {
+          var configuration = testMatrix.configurations
+              .singleWhere((c) => c.name == namedConfiguration);
+          addConfiguration(configuration, namedConfiguration);
+        } on StateError {
           var names = testMatrix.configurations
               .map((configuration) => configuration.name)
               .toList()
@@ -751,7 +752,6 @@
               ' The following configurations are available:\n'
               '  * ${names.join('\n  * ')}');
         }
-        addConfiguration(configuration, namedConfiguration);
       }
       return result;
     }
@@ -821,8 +821,8 @@
                   vmOptions: vmOptions,
                   dart2jsOptions: dart2jsOptions,
                   experiments: experiments,
-                  babel: data['babel'] as String,
-                  builderTag: data["builder-tag"] as String,
+                  babel: data['babel'] as String?,
+                  builderTag: data["builder-tag"] as String?,
                   useQemu: data["use-qemu"] as bool);
               addConfiguration(configuration);
             }
@@ -838,9 +838,9 @@
   ///
   /// If no selectors are explicitly given, uses the default suite patterns.
   Map<String, RegExp> _expandSelectors(Map<String, dynamic> configuration) {
-    var selectors = configuration['selectors'];
+    var selectors = configuration['selectors'] as List<String>?;
 
-    if (selectors == null || (selectors as List).isEmpty) {
+    if (selectors == null || selectors.isEmpty) {
       if (configuration['suite-dir'] != null) {
         var suitePath = Path(configuration['suite-dir'] as String);
         selectors = [suitePath.filename];
@@ -857,7 +857,7 @@
           ? (configuration['exclude-suite'] as String).split(',')
           : [];
       for (var exclude in excludeSuites) {
-        if ((selectors as List).contains(exclude)) {
+        if (selectors.contains(exclude)) {
           selectors.remove(exclude);
         } else {
           print("Warning: default selectors does not contain $exclude");
@@ -866,8 +866,8 @@
     }
 
     var selectorMap = <String, RegExp>{};
-    for (var i = 0; i < (selectors as List).length; i++) {
-      var pattern = selectors[i] as String;
+    for (var i = 0; i < selectors.length; i++) {
+      var pattern = selectors[i];
       var suite = pattern;
       var slashLocation = pattern.indexOf('/');
       if (slashLocation != -1) {
@@ -888,7 +888,7 @@
   }
 
   /// Print out usage information.
-  void _printHelp({bool verbose}) {
+  void _printHelp({bool verbose = false}) {
     print('''The Dart SDK's internal test runner.
 
     Usage: dart tools/test.dart [options] [selector]
@@ -925,8 +925,8 @@
   var testMatrix = TestMatrix.fromPath('tools/bots/test_matrix.json');
 
   // Default to only showing configurations for the current machine.
-  var systemOption = options['system'] as String;
-  var system = System.host;
+  var systemOption = options['system'] as String?;
+  System? system = System.host;
   if (systemOption == 'all') {
     system = null;
   } else if (systemOption != null) {
@@ -950,7 +950,7 @@
   var compilers = [...(options['compiler'] as List<String>).map(Compiler.find)];
   var runtimes = [...(options['runtime'] as List<String>).map(Runtime.find)];
 
-  NnbdMode nnbdMode;
+  NnbdMode? nnbdMode;
   if (options.containsKey('nnbd')) {
     nnbdMode = NnbdMode.find(options['nnbd'] as String);
   }
@@ -1006,7 +1006,8 @@
 }
 
 /// Throws an [OptionParseException] with [message].
-void _fail(String message) {
+// ignore: sdk_version_never
+Never _fail(String message) {
   throw OptionParseException(message);
 }
 
@@ -1018,10 +1019,10 @@
   config['sanitizer_options'].forEach((String key, dynamic value) {
     environment[key] = value as String;
   });
-  var symbolizerPath =
-      config['sanitizer_symbolizer'][Platform.operatingSystem] as String;
-  if (symbolizerPath != null) {
-    symbolizerPath = path.join(Directory.current.path, symbolizerPath);
+  final relativePath =
+      config['sanitizer_symbolizer'][Platform.operatingSystem] as String?;
+  if (relativePath != null) {
+    var symbolizerPath = path.join(Directory.current.path, relativePath);
     environment['ASAN_SYMBOLIZER_PATH'] = symbolizerPath;
     environment['LSAN_SYMBOLIZER_PATH'] = symbolizerPath;
     environment['MSAN_SYMBOLIZER_PATH'] = symbolizerPath;
diff --git a/pkg/test_runner/lib/src/output_log.dart b/pkg/test_runner/lib/src/output_log.dart
index 7f04b1d..755229c 100644
--- a/pkg/test_runner/lib/src/output_log.dart
+++ b/pkg/test_runner/lib/src/output_log.dart
@@ -17,10 +17,10 @@
   static const _maxLength = 10 * 1024 * 1024;
 
   final List<int> _data = [];
-  StreamSubscription _subscription;
+  StreamSubscription? _subscription;
 
   bool get hasNonUtf8 => _hasNonUtf8 ??= _checkUtf8();
-  bool _hasNonUtf8;
+  bool? _hasNonUtf8;
 
   bool get wasTruncated => _wasTruncated;
   bool _wasTruncated = false;
@@ -70,21 +70,21 @@
   }
 
   @override
-  Future addStream(Stream<List<int>> stream) {
+  Future<void> addStream(Stream<List<int>> stream) {
     _subscription = stream.listen(add);
-    return _subscription.asFuture();
+    return _subscription?.asFuture() ?? Future.value();
   }
 
   @override
-  Future close() => _subscription?.cancel();
+  Future<void> close() => _subscription?.cancel() ?? Future.value();
 
-  Future cancel() => _subscription?.cancel();
+  Future<void> cancel() => _subscription?.cancel() ?? Future.value();
 }
 
 /// An [OutputLog] that tees the output to a file as well.
 class FileOutputLog extends OutputLog {
   final File _outputFile;
-  IOSink _sink;
+  IOSink? _sink;
 
   FileOutputLog(this._outputFile);
 
@@ -92,22 +92,22 @@
   void add(List<int> data) {
     super.add(data);
     _sink ??= _outputFile.openWrite();
-    _sink.add(data);
+    _sink!.add(data);
   }
 
   @override
-  Future close() {
+  Future<void> close() {
     return Future.wait([
       super.close(),
-      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+      if (_sink != null) _sink!.flush().whenComplete(_sink!.close)
     ]);
   }
 
   @override
-  Future cancel() {
+  Future<void> cancel() {
     return Future.wait([
       super.cancel(),
-      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+      if (_sink != null) _sink!.flush().whenComplete(_sink!.close)
     ]);
   }
 }
diff --git a/pkg/test_runner/lib/src/path.dart b/pkg/test_runner/lib/src/path.dart
index ecf982f..7357190 100644
--- a/pkg/test_runner/lib/src/path.dart
+++ b/pkg/test_runner/lib/src/path.dart
@@ -182,24 +182,23 @@
     if (isEmpty) return false; // The canonical form of '' is '.'.
     if (_path == '.') return true;
     var segs = _path.split('/'); // Don't mask the getter 'segments'.
+    var start = 0;
     if (segs[0] == '') {
       // Absolute path
-      segs[0] = null; // Faster than removeRange().
+      start = 1; // Faster than removeRange().
     } else {
       // A canonical relative path may start with .. segments.
-      for (var pos = 0; pos < segs.length && segs[pos] == '..'; ++pos) {
-        segs[pos] = null;
-      }
+      for (; start < segs.length && segs[start] == '..'; ++start) {}
     }
     if (segs.last == '') segs.removeLast(); // Path ends with /.
     // No remaining segments can be ., .., or empty.
-    return !segs.any((s) => s == '' || s == '.' || s == '..');
+    return !segs.sublist(start).any((s) => s == '' || s == '.' || s == '..');
   }
 
   Path makeCanonical() {
     var isAbs = isAbsolute;
     var segs = segments();
-    String drive;
+    String? drive;
     if (isAbs && segs.isNotEmpty && segs[0].length == 2 && segs[0][1] == ':') {
       drive = segs[0];
       segs.removeRange(0, 1);
@@ -231,26 +230,17 @@
       }
     }
 
-    var segmentsToJoin = <String>[];
-    if (isAbs) {
-      segmentsToJoin.add('');
-      if (drive != null) {
-        segmentsToJoin.add(drive);
-      }
-    }
+    var segmentsToJoin = [
+      if (isAbs) '',
+      if (drive != null) drive,
+      if (newSegs.isEmpty) ...[
+        if (isAbs) '' else '.'
+      ] else ...[
+        ...newSegs,
+        if (hasTrailingSeparator) ''
+      ],
+    ];
 
-    if (newSegs.isEmpty) {
-      if (isAbs) {
-        segmentsToJoin.add('');
-      } else {
-        segmentsToJoin.add('.');
-      }
-    } else {
-      segmentsToJoin.addAll(newSegs);
-      if (hasTrailingSeparator) {
-        segmentsToJoin.add('');
-      }
-    }
     return Path._internal(segmentsToJoin.join('/'), isWindowsShare);
   }
 
diff --git a/pkg/test_runner/lib/src/process_queue.dart b/pkg/test_runner/lib/src/process_queue.dart
index bfce029..8610553 100644
--- a/pkg/test_runner/lib/src/process_queue.dart
+++ b/pkg/test_runner/lib/src/process_queue.dart
@@ -46,9 +46,9 @@
       this._eventListener,
       this._allDone,
       [bool verbose = false,
-      AdbDevicePool adbDevicePool]) {
+      AdbDevicePool? adbDevicePool]) {
     void setupForListing(TestCaseEnqueuer testCaseEnqueuer) {
-      _graph.sealed.listen((_) {
+      _graph.sealed.listen((Null _) {
         var testCases = testCaseEnqueuer.remainingTestCases.toList();
         testCases.sort((a, b) => a.displayName.compareTo(b.displayName));
 
@@ -67,17 +67,17 @@
     }
 
     TestCaseEnqueuer testCaseEnqueuer;
-    CommandQueue commandQueue;
+    late CommandQueue commandQueue;
 
     void setupForRunning(TestCaseEnqueuer testCaseEnqueuer) {
-      Timer _debugTimer;
+      Timer? _debugTimer;
       // If we haven't seen a single test finishing during a 10 minute period
       // something is definitely wrong, so we dump the debugging information.
       final debugTimerDuration = const Duration(minutes: 10);
 
       void cancelDebugTimer() {
         if (_debugTimer != null) {
-          _debugTimer.cancel();
+          _debugTimer!.cancel();
         }
       }
 
@@ -106,7 +106,7 @@
               for (var node in _graph.nodes) {
                 if (node.state == nodeState) {
                   var command = node.data;
-                  var testCases = testCaseEnqueuer.command2testCases[command];
+                  var testCases = testCaseEnqueuer.command2testCases[command]!;
                   print("  Command: $command");
                   for (var testCase in testCases) {
                     print("    Enqueued by: ${testCase.configurationString} "
@@ -119,15 +119,12 @@
               print("");
             }
           }
-
-          if (commandQueue != null) {
-            commandQueue.dumpState();
-          }
+          commandQueue.dumpState();
         });
       }
 
       // When the graph building is finished, notify event listeners.
-      _graph.sealed.listen((_) {
+      _graph.sealed.listen((Null _) {
         eventAllTestsKnown();
       });
 
@@ -255,7 +252,7 @@
   /// marked as a "timingDependency", so that it doesn't depend on the previous
   /// test completing successfully, just on it completing.
   void _add(TestCase testCase) {
-    Node<Command> lastNode;
+    Node<Command>? lastNode;
     for (var i = 0; i < testCase.configuration.repeat; ++i) {
       if (i > 0) {
         testCase = testCase.indexedCopy(i);
@@ -276,7 +273,7 @@
           command2testCases[command] = <TestCase>[];
         }
         // Keep mapping from command to all testCases that refer to it.
-        command2testCases[command].add(testCase);
+        command2testCases[command]!.add(testCase);
 
         lastNode = node;
         isFirstCommand = false;
@@ -393,7 +390,7 @@
     // state (Successful, Failed or UnableToRun).
     // So we're calling '_checkDone()' to check whether that condition is met
     // and we can cleanup.
-    graph.sealed.listen((event) {
+    graph.sealed.listen((Null _) {
       _checkDone();
     });
   }
@@ -420,8 +417,8 @@
       _numProcesses++;
       if (isBrowserCommand) _numBrowserProcesses++;
 
-      var node = enqueuer.command2node[command];
-      Iterable<TestCase> testCases = enqueuer.command2testCases[command];
+      var node = enqueuer.command2node[command]!;
+      Iterable<TestCase> testCases = enqueuer.command2testCases[command]!;
       // If a command is part of many TestCases we set the timeout to be
       // the maximum over all [TestCase.timeout]s. At some point, we might
       // eliminate [TestCase.timeout] completely and move it to [Command].
@@ -432,7 +429,7 @@
         print('Running "${command.displayName}" command: $command');
       }
 
-      executor.runCommand(node, command, timeout).then((CommandOutput output) {
+      executor.runCommand(command, timeout).then((CommandOutput output) {
         assert(command == output.command);
 
         _commandOutputStream.add(output);
@@ -494,22 +491,21 @@
 abstract class CommandExecutor {
   Future cleanup();
   // TODO(kustermann): The [timeout] parameter should be a property of Command.
-  Future<CommandOutput> runCommand(
-      Node<Command> node, Command command, int timeout);
+  Future<CommandOutput> runCommand(Command command, int timeout);
 }
 
 class CommandExecutorImpl implements CommandExecutor {
   final TestConfiguration globalConfiguration;
   final int maxProcesses;
   final int maxBrowserProcesses;
-  AdbDevicePool adbDevicePool;
+  AdbDevicePool? adbDevicePool;
 
   /// For dart2js and analyzer batch processing,
   /// we keep a list of batch processes.
   final _batchProcesses = <String, List<BatchRunnerProcess>>{};
 
   /// We keep a BrowserTestRunner for every configuration.
-  final _browserTestRunners = <TestConfiguration, BrowserTestRunner>{};
+  final _browserTestRunners = <TestConfiguration, Future<BrowserTestRunner>>{};
 
   bool _finishing = false;
 
@@ -529,9 +525,9 @@
       return Future.wait(futures);
     }
 
-    Future _terminateBrowserRunners() {
-      var futures =
-          _browserTestRunners.values.map((runner) => runner.terminate());
+    Future _terminateBrowserRunners() async {
+      var futures = _browserTestRunners.values
+          .map((runner) async => (await runner).terminate());
       return Future.wait(futures);
     }
 
@@ -541,7 +537,7 @@
     ]);
   }
 
-  Future<CommandOutput> runCommand(node, Command command, int timeout) {
+  Future<CommandOutput> runCommand(Command command, int timeout) {
     assert(!_finishing);
 
     Future<CommandOutput> runCommand(int retriesLeft) {
@@ -583,8 +579,7 @@
       return command.run();
     } else if (command is AdbPrecompilationCommand ||
         command is AdbDartkCommand) {
-      assert(adbDevicePool != null);
-      return adbDevicePool.acquireDevice().then((AdbDevice device) async {
+      return adbDevicePool!.acquireDevice().then((AdbDevice device) async {
         try {
           if (command is AdbPrecompilationCommand) {
             return await _runAdbPrecompilationCommand(device, command, timeout);
@@ -593,7 +588,7 @@
                 device, command as AdbDartkCommand, timeout);
           }
         } finally {
-          adbDevicePool.releaseDevice(device);
+          adbDevicePool!.releaseDevice(device);
         }
       });
     } else if (command is CompilationCommand &&
@@ -607,7 +602,7 @@
               configuration: globalConfiguration)
           .run();
     } else if (command is RRCommand) {
-      return command.run(timeout);
+      return command.run(timeout, globalConfiguration);
     } else {
       throw ArgumentError("Unknown command type ${command.runtimeType}.");
     }
@@ -684,7 +679,7 @@
     await device.waitForBootCompleted();
     await device.waitForDevice();
 
-    AdbCommandResult result;
+    late AdbCommandResult result;
     for (var i = 0; i < steps.length; i++) {
       var fun = steps[i];
       var commandStopwatch = Stopwatch()..start();
@@ -744,7 +739,7 @@
     await device.waitForBootCompleted();
     await device.waitForDevice();
 
-    AdbCommandResult result;
+    late AdbCommandResult result;
     for (var i = 0; i < steps.length; i++) {
       var step = steps[i];
       var commandStopwatch = Stopwatch()..start();
@@ -771,14 +766,10 @@
 
   BatchRunnerProcess _getBatchRunner(String identifier) {
     // Start batch processes if needed.
-    var runners = _batchProcesses[identifier];
-    if (runners == null) {
-      runners = List<BatchRunnerProcess>.filled(maxProcesses, null);
-      for (var i = 0; i < maxProcesses; i++) {
-        runners[i] = BatchRunnerProcess(useJson: identifier == "fasta");
-      }
-      _batchProcesses[identifier] = runners;
-    }
+    var runners = _batchProcesses.putIfAbsent(
+        identifier,
+        () => List<BatchRunnerProcess>.generate(maxProcesses,
+            (_) => BatchRunnerProcess(useJson: identifier == "fasta")));
 
     for (var runner in runners) {
       if (!runner._currentlyRunning) return runner;
@@ -795,80 +786,74 @@
     }
 
     var browserTest = BrowserTest(browserCommand.url, callback, timeout);
+    (await _getBrowserTestRunner(browserCommand.configuration))!
+        .enqueueTest(browserTest);
+    return completer.future;
+  }
+
+  Future<BrowserTestRunner?> _getBrowserTestRunner(
+      TestConfiguration configuration) async {
     for (var failures = 0; failures < 10; failures++) {
-      var testRunner =
-          await _getBrowserTestRunner(browserCommand.configuration);
-      if (testRunner != null) {
-        testRunner.enqueueTest(browserTest);
-        return completer.future;
+      BrowserTestRunner? runner;
+      try {
+        runner = await _browserTestRunners.putIfAbsent(
+            configuration,
+            () => BrowserTestRunner(configuration, globalConfiguration.localIP,
+                    maxBrowserProcesses)
+                .start());
+      } catch (error) {
+        DebugLogger.error('Failed to start browser test runner.', error);
+        _browserTestRunners.remove(configuration);
+        await runner!.terminate();
+        continue;
       }
+      if (globalConfiguration.isVerbose) {
+        runner.logger = DebugLogger.info;
+      }
+      return runner;
     }
     print('FATAL: Failed to get a browser test runner 10 times in a row.');
     io.exit(1);
   }
-
-  Future<BrowserTestRunner> _getBrowserTestRunner(
-      TestConfiguration configuration) async {
-    if (_browserTestRunners[configuration] == null) {
-      var testRunner = BrowserTestRunner(
-          configuration, globalConfiguration.localIP, maxBrowserProcesses);
-      if (globalConfiguration.isVerbose) {
-        testRunner.logger = DebugLogger.info;
-      }
-      _browserTestRunners[configuration] = testRunner;
-      if (!await testRunner.start()) {
-        DebugLogger.error('Failed to start browser test runner.');
-        _browserTestRunners.remove(configuration);
-        await testRunner.terminate();
-      }
-    }
-    return _browserTestRunners[configuration];
-  }
 }
 
 bool shouldRetryCommand(CommandOutput output) {
-  if (!output.successful) {
-    List<String> stdout, stderr;
+  if (output.successful) {
+    return false;
+  }
 
-    decodeOutput() {
-      if (stdout == null && stderr == null) {
-        stdout = decodeUtf8(output.stderr).split("\n");
-        stderr = decodeUtf8(output.stderr).split("\n");
-      }
-    }
+  late var stdout = decodeUtf8(output.stdout).split("\n");
+  late var stderr = decodeUtf8(output.stderr).split("\n");
 
-    final command = output.command;
+  final command = output.command;
 
-    // The dartk batch compiler sometimes runs out of memory. In such a case we
-    // will retry running it.
-    if (command is VMKernelCompilationCommand) {
-      if (output.hasCrashed) {
-        bool containsOutOfMemoryMessage(String line) {
-          return line.contains('Exhausted heap space, trying to allocat');
-        }
-
-        decodeOutput();
-        if (stdout.any(containsOutOfMemoryMessage) ||
-            stderr.any(containsOutOfMemoryMessage)) {
-          return true;
-        }
-      }
-    }
-
-    if (io.Platform.operatingSystem == 'linux') {
-      decodeOutput();
-      // No matter which command we ran: If we get failures due to the
-      // "xvfb-run" issue 7564, try re-running the test.
-      bool containsFailureMsg(String line) {
-        return line.contains(_cannotOpenDisplayMessage) ||
-            line.contains(_failedToRunCommandMessage);
+  // The dartk batch compiler sometimes runs out of memory. In such a case we
+  // will retry running it.
+  if (command is VMKernelCompilationCommand) {
+    if (output.hasCrashed) {
+      bool containsOutOfMemoryMessage(String line) {
+        return line.contains('Exhausted heap space, trying to allocat');
       }
 
-      if (stdout.any(containsFailureMsg) || stderr.any(containsFailureMsg)) {
+      if (stdout.any(containsOutOfMemoryMessage) ||
+          stderr.any(containsOutOfMemoryMessage)) {
         return true;
       }
     }
   }
+
+  if (io.Platform.operatingSystem == 'linux') {
+    // No matter which command we ran: If we get failures due to the
+    // "xvfb-run" issue 7564, try re-running the test.
+    bool containsFailureMsg(String line) {
+      return line.contains(_cannotOpenDisplayMessage) ||
+          line.contains(_failedToRunCommandMessage);
+    }
+
+    if (stdout.any(containsFailureMsg) || stderr.any(containsFailureMsg)) {
+      return true;
+    }
+  }
   return false;
 }
 
@@ -913,14 +898,14 @@
         assert(_completedStates.contains(event.to));
         assert(_outputs[command] != null);
 
-        _completeTestCasesIfPossible(_enqueuer.command2testCases[command]);
+        _completeTestCasesIfPossible(_enqueuer.command2testCases[command]!);
         _checkDone();
       }
     });
 
     // Listen also for GraphSealedEvents. If there is not a single node in the
     // graph, we still want to finish after the graph was sealed.
-    _graph.sealed.listen((_) {
+    _graph.sealed.listen((Null _) {
       if (!_closed && _enqueuer.remainingTestCases.isEmpty) {
         _controller.close();
         _closed = true;
@@ -973,25 +958,25 @@
   /// JSON-encoded list of strings.
   final bool _useJson;
 
-  Completer<CommandOutput> _completer;
-  ProcessCommand _command;
-  List<String> _arguments;
-  String _runnerType;
+  Completer<CommandOutput>? _completer;
+  late ProcessCommand _command;
+  late List<String> _arguments;
+  String? _runnerType;
 
-  io.Process _process;
-  Map<String, String> _processEnvironmentOverrides;
-  Completer<Null> _stdoutCompleter;
-  Completer<Null> _stderrCompleter;
-  StreamSubscription<String> _stdoutSubscription;
-  StreamSubscription<String> _stderrSubscription;
-  Function _processExitHandler;
+  io.Process? _process;
+  Map<String, String>? _processEnvironmentOverrides;
+  late Completer<Null> _stdoutCompleter;
+  late Completer<Null> _stderrCompleter;
+  late StreamSubscription<String> _stdoutSubscription;
+  late StreamSubscription<String> _stderrSubscription;
+  late Function _processExitHandler;
 
   bool _currentlyRunning = false;
-  OutputLog _testStdout;
-  OutputLog _testStderr;
-  String _status;
-  DateTime _startTime;
-  Timer _timer;
+  late OutputLog _testStdout;
+  late OutputLog _testStderr;
+  String? _status;
+  late DateTime _startTime;
+  Timer? _timer;
   int _testCount = 0;
 
   BatchRunnerProcess({bool useJson = true}) : _useJson = useJson;
@@ -1027,26 +1012,26 @@
           doStartTest(command, timeout);
         });
       };
-      _process.kill();
+      _process!.kill();
       _stdoutSubscription.cancel();
       _stderrSubscription.cancel();
     } else {
       doStartTest(command, timeout);
     }
-    return _completer.future;
+    return _completer!.future;
   }
 
   Future<bool> terminate() {
     if (_process == null) return Future.value(true);
     var terminateCompleter = Completer<bool>();
     final sigkillTimer = Timer(const Duration(seconds: 5), () {
-      _process.kill(io.ProcessSignal.sigkill);
+      _process?.kill(io.ProcessSignal.sigkill);
     });
     _processExitHandler = (_) {
       sigkillTimer.cancel();
       terminateCompleter.complete(true);
     };
-    _process.kill();
+    _process!.kill();
     _stdoutSubscription.cancel();
     _stderrSubscription.cancel();
 
@@ -1063,7 +1048,7 @@
     _timer = Timer(Duration(seconds: timeout), _timeoutHandler);
 
     var line = _createArgumentsLine(_arguments, timeout);
-    _process.stdin.write(line);
+    _process!.stdin.write(line);
     _stdoutSubscription.resume();
     _stderrSubscription.resume();
     Future.wait([_stdoutCompleter.future, _stderrCompleter.future])
@@ -1081,7 +1066,7 @@
   void _reportResult() {
     if (!_currentlyRunning) return;
 
-    var outcome = _status.split(" ")[2];
+    var outcome = _status!.split(" ")[2];
     var exitCode = 0;
     if (outcome == "CRASH") exitCode = unhandledCompilerExceptionExitCode;
     if (outcome == "PARSE_FAIL") exitCode = parseFailExitCode;
@@ -1102,7 +1087,7 @@
         DateTime.now().difference(_startTime),
         false);
     assert(_completer != null);
-    _completer.complete(output);
+    _completer!.complete(output);
     _completer = null;
     _currentlyRunning = false;
   }
@@ -1110,7 +1095,7 @@
   void Function(int) makeExitHandler(String status) {
     return (int exitCode) {
       if (_currentlyRunning) {
-        if (_timer != null) _timer.cancel();
+        if (_timer != null) _timer!.cancel();
         _status = status;
         _stdoutSubscription.cancel();
         _stderrSubscription.cancel();
@@ -1124,74 +1109,21 @@
 
   void _timeoutHandler() {
     _processExitHandler = makeExitHandler(">>> TEST TIMEOUT");
-    _process.kill();
+    _process!.kill();
   }
 
-  void _startProcess(void Function() callback) {
-    assert(_command is ProcessCommand);
+  void _startProcess(void Function() callback) async {
     var executable = _command.executable;
     var arguments = _command.batchArguments.toList();
     arguments.add('--batch');
     var environment = Map<String, String>.from(io.Platform.environment);
     if (_processEnvironmentOverrides != null) {
-      for (var key in _processEnvironmentOverrides.keys) {
-        environment[key] = _processEnvironmentOverrides[key];
-      }
+      environment.addAll(_processEnvironmentOverrides!);
     }
-    var processFuture =
-        io.Process.start(executable, arguments, environment: environment);
-    processFuture.then<dynamic>((io.Process p) {
-      _process = p;
-
-      var _stdoutStream = _process.stdout
-          .transform(utf8.decoder)
-          .transform(const LineSplitter());
-      _stdoutSubscription = _stdoutStream.listen((String line) {
-        if (line.startsWith('>>> TEST')) {
-          _status = line;
-        } else if (line.startsWith('>>> BATCH')) {
-          // ignore
-        } else if (line.startsWith('>>> ')) {
-          throw Exception("Unexpected command from batch runner: '$line'.");
-        } else {
-          _testStdout.add(encodeUtf8(line));
-          _testStdout.add("\n".codeUnits);
-        }
-        if (_status != null) {
-          _stdoutSubscription.pause();
-          _timer.cancel();
-          _stdoutCompleter.complete(null);
-        }
-      });
-      _stdoutSubscription.pause();
-
-      var _stderrStream = _process.stderr
-          .transform(utf8.decoder)
-          .transform(const LineSplitter());
-      _stderrSubscription = _stderrStream.listen((String line) {
-        if (line.startsWith('>>> EOF STDERR')) {
-          _stderrSubscription.pause();
-          _stderrCompleter.complete(null);
-        } else {
-          _testStderr.add(encodeUtf8(line));
-          _testStderr.add("\n".codeUnits);
-        }
-      });
-      _stderrSubscription.pause();
-
-      _processExitHandler = makeExitHandler(">>> TEST CRASH");
-      _process.exitCode.then((exitCode) {
-        _processExitHandler(exitCode);
-      });
-
-      _process.stdin.done.catchError((err) {
-        print('Error on batch runner input stream stdin');
-        print('  Previous test\'s status: $_status');
-        print('  Error: $err');
-        throw err;
-      });
-      callback();
-    }).catchError((e) {
+    try {
+      _process = await io.Process.start(executable, arguments,
+          environment: environment);
+    } catch (e) {
       // TODO(floitsch): should we try to report the stacktrace?
       print("Process error:");
       print("  Command: $executable ${arguments.join(' ')} ($_arguments)");
@@ -1200,10 +1132,59 @@
       // it will always fail. So rather than re-trying a 1000+ times, we
       // exit.
       io.exit(1);
+    }
+
+    var stdoutStream = _process!.stdout
+        .transform(utf8.decoder)
+        .transform(const LineSplitter());
+    _stdoutSubscription = stdoutStream.listen((String line) {
+      if (line.startsWith('>>> TEST')) {
+        _status = line;
+      } else if (line.startsWith('>>> BATCH')) {
+        // ignore
+      } else if (line.startsWith('>>> ')) {
+        throw Exception("Unexpected command from batch runner: '$line'.");
+      } else {
+        _testStdout.add(utf8.encode(line));
+        _testStdout.add("\n".codeUnits);
+      }
+      if (_status != null) {
+        _stdoutSubscription.pause();
+        _timer!.cancel();
+        _stdoutCompleter.complete(null);
+      }
     });
+    _stdoutSubscription.pause();
+
+    var stderrStream = _process!.stderr
+        .transform(utf8.decoder)
+        .transform(const LineSplitter());
+    _stderrSubscription = stderrStream.listen((String line) {
+      if (line.startsWith('>>> EOF STDERR')) {
+        _stderrSubscription.pause();
+        _stderrCompleter.complete(null);
+      } else {
+        _testStderr.add(utf8.encode(line));
+        _testStderr.add("\n".codeUnits);
+      }
+    });
+    _stderrSubscription.pause();
+
+    _processExitHandler = makeExitHandler(">>> TEST CRASH");
+    _process!.exitCode.then((exitCode) {
+      _processExitHandler(exitCode);
+    });
+
+    _process!.stdin.done.catchError((Object err) {
+      print('Error on batch runner input stream stdin');
+      print('  Previous test\'s status: $_status');
+      print('  Error: $err');
+      throw err;
+    });
+    callback();
   }
 
-  bool _dictEquals(Map a, Map b) {
+  bool _dictEquals(Map? a, Map? b) {
     if (a == null) return b == null;
     if (b == null) return false;
     if (a.length != b.length) return false;
diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart
index ccabb36..02949d8 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -17,7 +17,7 @@
 /// shared between multiple test cases, it should not be mutated after
 /// construction.
 abstract class RuntimeConfiguration {
-  TestConfiguration _configuration;
+  late TestConfiguration _configuration;
 
   static RuntimeConfiguration _makeInstance(TestConfiguration configuration) {
     switch (configuration.runtime) {
@@ -51,14 +51,13 @@
       case Runtime.dartPrecompiled:
         if (configuration.system == System.android) {
           return DartPrecompiledAdbRuntimeConfiguration(
-            useElf: configuration.useElf,
+            configuration.useElf,
           );
         } else {
           return DartPrecompiledRuntimeConfiguration(
-            useElf: configuration.useElf,
+            configuration.useElf,
           );
         }
-        break;
     }
     throw "unreachable";
   }
@@ -70,15 +69,15 @@
   RuntimeConfiguration._subclass();
 
   int timeoutMultiplier(
-      {Mode mode,
+      {required Mode mode,
       bool isChecked = false,
       bool isReload = false,
-      Architecture arch}) {
+      required Architecture arch}) {
     return 1;
   }
 
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
@@ -152,7 +151,7 @@
   NoneRuntimeConfiguration() : super._subclass();
 
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
@@ -179,13 +178,13 @@
   D8RuntimeConfiguration() : super('d8');
 
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
     // TODO(ahe): Avoid duplication of this method between d8 and jsshell.
-    checkArtifact(artifact);
+    checkArtifact(artifact!);
     return [
       JSCommandLineCommand(moniker, d8FileName, arguments, environmentOverrides)
     ];
@@ -201,12 +200,12 @@
   JsshellRuntimeConfiguration() : super('jsshell');
 
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    checkArtifact(artifact);
+    checkArtifact(artifact!);
     return [
       JSCommandLineCommand(
           moniker, jsShellFileName, arguments, environmentOverrides)
@@ -245,10 +244,10 @@
   DartVmRuntimeConfiguration() : super._subclass();
 
   int timeoutMultiplier(
-      {Mode mode,
+      {required Mode mode,
       bool isChecked = false,
       bool isReload = false,
-      Architecture arch}) {
+      required Architecture arch}) {
     var multiplier = 1;
 
     switch (arch) {
@@ -284,13 +283,13 @@
 //// The standalone Dart VM binary, "dart" or "dart.exe".
 class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    var script = artifact.filename;
-    var type = artifact.mimeType;
+    var script = artifact?.filename;
+    var type = artifact?.mimeType;
     if (script != null &&
         type != 'application/dart' &&
         type != 'application/dart-snapshot' &&
@@ -306,7 +305,7 @@
       executable = dartVmExecutableFileName;
     }
     if (_configuration.useQemu) {
-      final config = QemuConfig.all[_configuration.architecture];
+      final config = QemuConfig.all[_configuration.architecture]!;
       arguments.insert(0, executable);
       arguments.insertAll(0, config.arguments);
       executable = config.executable;
@@ -321,16 +320,16 @@
 
 class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
   final bool useElf;
-  DartPrecompiledRuntimeConfiguration({this.useElf});
+  DartPrecompiledRuntimeConfiguration(this.useElf);
 
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    var script = artifact.filename;
-    var type = artifact.mimeType;
+    var script = artifact?.filename;
+    var type = artifact?.mimeType;
     if (script != null && type != 'application/dart-precompiled') {
       throw "dart_precompiled cannot run files of type '$type'.";
     }
@@ -338,7 +337,7 @@
     var executable = dartPrecompiledBinaryFileName;
 
     if (_configuration.useQemu) {
-      final config = QemuConfig.all[_configuration.architecture];
+      final config = QemuConfig.all[_configuration.architecture]!;
       arguments.insert(0, executable);
       arguments.insertAll(0, config.arguments);
       executable = config.executable;
@@ -357,13 +356,13 @@
   static const String deviceTestDir = '/data/local/tmp/testing/test';
 
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    var script = artifact.filename;
-    var type = artifact.mimeType;
+    var script = artifact?.filename;
+    var type = artifact?.mimeType;
     if (script != null && type != 'application/kernel-ir-fully-linked') {
       throw "dart cannot run files of type '$type'.";
     }
@@ -372,7 +371,7 @@
     var processTest = processTestBinaryFileName;
     var abstractSocketTest = abstractSocketTestBinaryFileName;
     return [
-      AdbDartkCommand(buildPath, processTest, abstractSocketTest, script,
+      AdbDartkCommand(buildPath, processTest, abstractSocketTest, script!,
           arguments, extraLibs)
     ];
   }
@@ -384,16 +383,16 @@
   static const deviceTestDir = '/data/local/tmp/precompilation-testing/test';
 
   final bool useElf;
-  DartPrecompiledAdbRuntimeConfiguration({this.useElf});
+  DartPrecompiledAdbRuntimeConfiguration(this.useElf);
 
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    var script = artifact.filename;
-    var type = artifact.mimeType;
+    var script = artifact?.filename;
+    var type = artifact?.mimeType;
     if (script != null && type != 'application/dart-precompiled') {
       throw "dart_precompiled cannot run files of type '$type'.";
     }
@@ -402,7 +401,7 @@
     var abstractSocketTest = abstractSocketTestBinaryFileName;
     return [
       AdbPrecompilationCommand(buildDir, processTest, abstractSocketTest,
-          script, arguments, useElf, extraLibs)
+          script!, arguments, useElf, extraLibs)
     ];
   }
 }
@@ -410,13 +409,13 @@
 class DartkFuchsiaEmulatorRuntimeConfiguration
     extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    var script = artifact.filename;
-    var type = artifact.mimeType;
+    var script = artifact?.filename;
+    var type = artifact?.mimeType;
     if (script != null &&
         type != 'application/dart' &&
         type != 'application/dart-snapshot' &&
@@ -441,7 +440,7 @@
 // TODO(ahe): Remove this class.
 class DummyRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
-      CommandArtifact artifact,
+      CommandArtifact? artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
diff --git a/pkg/test_runner/lib/src/service/service.dart b/pkg/test_runner/lib/src/service/service.dart
deleted file mode 100644
index 25ac0b7..0000000
--- a/pkg/test_runner/lib/src/service/service.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-enum ServiceState {
-  created,
-  starting,
-  running,
-  failed,
-  stopped,
-}
diff --git a/pkg/test_runner/lib/src/service/web_driver_service.dart b/pkg/test_runner/lib/src/service/web_driver_service.dart
index 9719116..d11357f 100644
--- a/pkg/test_runner/lib/src/service/web_driver_service.dart
+++ b/pkg/test_runner/lib/src/service/web_driver_service.dart
@@ -8,7 +8,6 @@
 import 'package:smith/smith.dart';
 
 import '../test_progress.dart';
-import 'service.dart';
 
 const safariDriverPort = 7055;
 
@@ -18,56 +17,58 @@
     Runtime.safari,
   };
 
-  final String _driverExecutable;
-  final List<String> _driverArguments;
-  Future<void> _started;
+  bool _running = false;
   Process _process;
 
-  ServiceState state = ServiceState.created;
   final int port;
 
-  WebDriverService(this._driverExecutable, this._driverArguments, this.port);
-
-  Future<void> start() {
-    if (_started != null) {
-      return _started;
-    }
-    return _started = () async {
-      state = ServiceState.starting;
-      try {
-        _process = await Process.start(
-            _driverExecutable, ['--port', '$port', ..._driverArguments]);
-        _process.exitCode.then((exitCode) {
-          if (state != ServiceState.stopped) {
-            state = ServiceState.failed;
-            print('$runtimeType stopped unexpectedly: $exitCode');
-          }
-        });
-        state = ServiceState.running;
-        print('Started $runtimeType on port $port');
-      } catch (error) {
-        state = ServiceState.failed;
-        print('Failed to start $runtimeType: $error');
-        rethrow;
+  WebDriverService._(this.port, this._process) {
+    _process.exitCode.then((exitCode) {
+      if (_running) {
+        print('WebDriverService stopped unexpectedly: $exitCode');
+        _running = false;
       }
-    }();
+    });
   }
 
   @override
   void allDone() {
-    state = ServiceState.stopped;
-    _process?.kill();
+    _process.kill();
+    _running = false;
+  }
+
+  static Future<WebDriverService> startServiceForRuntime(
+      Runtime runtime) async {
+    var service = _instances[runtime];
+    String driverExecutable;
+    List<String> driverArguments;
+    int port;
+    if (service != null) {
+      return service;
+    }
+    switch (runtime) {
+      case Runtime.safari:
+        driverExecutable = '/usr/bin/safaridriver';
+        driverArguments = const [];
+        port = safariDriverPort;
+        break;
+      default:
+        throw ArgumentError.value(runtime, 'runtime', 'Unsupported runtime');
+    }
+    try {
+      var process = await Process.start(
+          driverExecutable, ['--port', '$port', ...driverArguments]);
+      print('Started WebDriverService on port $port');
+      return _instances[runtime] =
+          WebDriverService._(safariDriverPort, process);
+    } catch (error) {
+      print('Failed to start $runtime web driver service: $error');
+      rethrow;
+    }
   }
 
   factory WebDriverService.fromRuntime(Runtime runtime) {
-    return _instances.putIfAbsent(runtime, () {
-      switch (runtime) {
-        case Runtime.safari:
-          return WebDriverService(
-              '/usr/bin/safaridriver', [], safariDriverPort);
-        default:
-          throw ArgumentError.value(runtime, 'runtime', 'Unsupported runtime');
-      }
-    });
+    return _instances[runtime] ??
+        (throw ArgumentError.value(runtime, 'runtime', 'Service unavailable'));
   }
 }
diff --git a/pkg/test_runner/lib/src/static_error.dart b/pkg/test_runner/lib/src/static_error.dart
index 41df706..c24e8f8 100644
--- a/pkg/test_runner/lib/src/static_error.dart
+++ b/pkg/test_runner/lib/src/static_error.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Only needed so that [TestFile] can be referenced in doc comments.
+import 'package:collection/collection.dart' show IterableExtension;
 import 'test_file.dart';
 
 /// A front end that can report static errors.
@@ -22,7 +23,7 @@
 
   /// Gets the source whose lowercase name is [name] or `null` if no source
   /// with that name could be found.
-  static ErrorSource find(String /*!*/ name) {
+  static ErrorSource? find(String name) {
     for (var source in all) {
       if (source.marker == name) return source;
     }
@@ -121,11 +122,10 @@
   ///
   /// Also describes any mismatches between the context messages in the expected
   /// and actual errors.
-  static String validateExpectations(
-      Iterable<StaticError /*!*/ > expectedErrors,
-      Iterable<StaticError /*!*/ > actualErrors) {
-    var expected = expectedErrors.toList();
-    var actual = actualErrors.toList();
+  static String? validateExpectations(Iterable<StaticError> expectedErrors,
+      Iterable<StaticError> actualErrors) {
+    var expected = <StaticError?>[...expectedErrors];
+    var actual = <StaticError?>[...actualErrors];
 
     // Put them in a deterministic order.
     expected.sort();
@@ -140,17 +140,17 @@
       for (var j = 0; j < actual.length; j++) {
         if (actual[j] == null) continue;
 
-        if (expected[i]._matchMessage(actual[j]) &&
-            expected[i]._matchLocation(actual[j])) {
+        if (expected[i]!._matchMessage(actual[j]) &&
+            expected[i]!._matchLocation(actual[j]!)) {
           // Report any mismatches in the context messages.
-          expected[i]._validateContext(actual[j], buffer);
+          expected[i]!._validateContext(actual[j], buffer);
 
           actual[j] = null;
           matchedExpected = true;
 
           // If the expected error is unspecified, keep going so that it can
           // consume multiple errors on the same line.
-          if (expected[i].isSpecified) break;
+          if (expected[i]!.isSpecified) break;
         }
       }
 
@@ -164,7 +164,7 @@
     if (expected.isEmpty && actual.isEmpty && buffer.isEmpty) return null;
 
     void fail(StaticError error, String label, String contextLabel,
-        [String secondary]) {
+        [String? secondary]) {
       if (error.isContext) label = contextLabel;
 
       if (error.isSpecified) {
@@ -185,11 +185,11 @@
       for (var j = 0; j < actual.length; j++) {
         if (actual[j] == null) continue;
 
-        if (expected[i].message == actual[j].message) {
-          fail(expected[i], "Wrong error location", "Wrong context location",
-              expected[i]._locationError(actual[j]));
+        if (expected[i]!.message == actual[j]!.message) {
+          fail(expected[i]!, "Wrong error location", "Wrong context location",
+              expected[i]!._locationError(actual[j]!));
           // Report any mismatches in the context messages.
-          expected[i]._validateContext(actual[j], buffer);
+          expected[i]!._validateContext(actual[j], buffer);
 
           // Only report this mismatch once.
           expected[i] = null;
@@ -205,11 +205,11 @@
       for (var j = 0; j < actual.length; j++) {
         if (actual[j] == null) continue;
 
-        if (expected[i]._matchLocation(actual[j])) {
-          fail(actual[j], "Wrong message at", "Wrong context message at",
-              "Expected: ${expected[i].message}");
+        if (expected[i]!._matchLocation(actual[j]!)) {
+          fail(actual[j]!, "Wrong message at", "Wrong context message at",
+              "Expected: ${expected[i]!.message}");
           // Report any mismatches in the context messages.
-          expected[i]._validateContext(actual[j], buffer);
+          expected[i]!._validateContext(actual[j], buffer);
 
           // Only report this mismatch once.
           expected[i] = null;
@@ -222,14 +222,14 @@
     // Any remaining expected errors are missing.
     for (var i = 0; i < expected.length; i++) {
       if (expected[i] == null) continue;
-      fail(expected[i], "Missing expected error at",
+      fail(expected[i]!, "Missing expected error at",
           "Missing expected context message at");
     }
 
     // Any remaining actual errors are unexpected.
     for (var j = 0; j < actual.length; j++) {
       if (actual[j] == null) continue;
-      fail(actual[j], "Unexpected error at", "Unexpected context message at");
+      fail(actual[j]!, "Unexpected error at", "Unexpected context message at");
     }
 
     return buffer.toString().trimRight();
@@ -245,12 +245,12 @@
   ///
   /// `0` means no length was reported. The CFE only reports error location,
   /// but not length.
-  final int /*!*/ length;
+  final int length;
 
   /// The front end this error is for.
   final ErrorSource source;
 
-  final String /*!*/ message;
+  final String message;
 
   /// Additional context messages associated with this error.
   final List<StaticError> contextMessages = [];
@@ -273,13 +273,11 @@
   /// error is tested, a front end is expected to report *some* error on that
   /// error's line, but it can be any location, error code, or message.
   StaticError(this.source, this.message,
-      {this.line, this.column, this.length = 0, Set<int> sourceLines})
-      : sourceLines = {...?sourceLines} {
-    // Must have a location.
-    assert(line != null);
-    assert(column != null);
-    assert(length != null);
-  }
+      {required this.line,
+      required this.column,
+      this.length = 0,
+      Set<int>? sourceLines})
+      : sourceLines = {...?sourceLines};
 
   /// A textual description of this error's location.
   String get location {
@@ -314,7 +312,7 @@
         return false;
     }
 
-    throw FallThroughError();
+    throw UnsupportedError("Unsupported source: ${source.name}");
   }
 
   String toString() {
@@ -378,8 +376,8 @@
   /// Returns true if [actual]'s message matches this one.
   ///
   /// Takes unspecified errors into account.
-  bool _matchMessage(StaticError actual) {
-    return !isSpecified || message == actual.message;
+  bool _matchMessage(StaticError? actual) {
+    return !isSpecified || message == actual!.message;
   }
 
   /// Returns true if [actual]'s location matches this one.
@@ -432,12 +430,12 @@
   /// Validates that this expected error's context messages match [actual]'s.
   ///
   /// Writes any mismatch errors to [buffer].
-  void _validateContext(StaticError actual, StringBuffer buffer) {
+  void _validateContext(StaticError? actual, StringBuffer buffer) {
     // If the expected error has no context, then ignore actual context
     // messages.
     if (contextMessages.isEmpty) return;
 
-    var result = validateExpectations(contextMessages, actual.contextMessages);
+    var result = validateExpectations(contextMessages, actual!.contextMessages);
     if (result != null) {
       buffer.writeln(result);
       buffer.writeln();
@@ -529,7 +527,7 @@
         _parseErrors(
             line: _lastRealLine,
             column: sourceLine.indexOf("^") + 1,
-            length: match[1].length);
+            length: match[1]!.length);
         _advance();
         continue;
       }
@@ -539,8 +537,8 @@
         var lineCapture = match[1];
         _parseErrors(
             line: lineCapture == null ? _lastRealLine : int.parse(lineCapture),
-            column: int.parse(match[2]),
-            length: int.parse(match[3]));
+            column: int.parse(match[2]!),
+            length: int.parse(match[3]!));
         _advance();
         continue;
       }
@@ -550,7 +548,7 @@
         var lineCapture = match[1];
         _parseErrors(
             line: lineCapture == null ? _lastRealLine : int.parse(lineCapture),
-            column: int.parse(match[2]));
+            column: int.parse(match[2]!));
         _advance();
         continue;
       }
@@ -564,8 +562,7 @@
   }
 
   /// Finishes parsing a series of error expectations after parsing a location.
-  void _parseErrors(
-      {/*required*/ int line, /*required*/ int column, int length = 0}) {
+  void _parseErrors({required int line, required int column, int length = 0}) {
     var locationLine = _currentLine;
     var parsedError = false;
 
@@ -574,16 +571,16 @@
       var match = _errorMessageRegExp.firstMatch(_peek(1));
       if (match == null) break;
 
-      var number = match[2] != null ? int.parse(match[2]) : null;
+      var number = match[2] != null ? int.parse(match[2]!) : null;
 
-      var sourceName = match[1];
+      var sourceName = match[1]!;
       var source = ErrorSource.find(sourceName) ??
           _fail("Unknown front end '[$sourceName]'.");
       if (source == ErrorSource.context && number == null) {
         _fail("Context messages must have an error number.");
       }
 
-      var message = match[3] /*!*/;
+      var message = match[3]!;
       _advance();
       var sourceLines = {locationLine, _currentLine};
 
@@ -602,7 +599,7 @@
         var messageMatch = _errorMessageRestRegExp.firstMatch(nextLine);
         if (messageMatch == null) break;
 
-        message += "\n" + messageMatch[1];
+        message += "\n" + messageMatch[1]!;
         _advance();
         sourceLines.add(_currentLine);
       }
@@ -632,9 +629,8 @@
       if (number != null) {
         // Make sure two errors don't claim the same number.
         if (source != ErrorSource.context) {
-          var existingError = _errors.firstWhere(
-              (error) => _errorNumbers[error] == number,
-              orElse: () => null);
+          var existingError = _errors
+              .firstWhereOrNull((error) => _errorNumbers[error] == number);
           if (existingError != null) {
             _fail("Already have an error with number $number.");
           }
@@ -663,8 +659,8 @@
     for (var contextMessage in _contextMessages) {
       var number = _errorNumbers[contextMessage];
 
-      var error = _errors.firstWhere((error) => _errorNumbers[error] == number,
-          orElse: () => null);
+      var error =
+          _errors.firstWhereOrNull((error) => _errorNumbers[error] == number);
       if (error == null) {
         throw FormatException("No error with number $number for context "
             "message '${contextMessage.message}'.");
@@ -679,9 +675,8 @@
       var number = _errorNumbers[error];
       if (number == null) continue;
 
-      var context = _contextMessages.firstWhere(
-          (context) => _errorNumbers[context] == number,
-          orElse: () => null);
+      var context = _contextMessages
+          .firstWhereOrNull((context) => _errorNumbers[context] == number);
       if (context == null) {
         throw FormatException("Missing context for numbered error $number "
             "'${error.message}'.");
diff --git a/pkg/test_runner/lib/src/status_reporter.dart b/pkg/test_runner/lib/src/status_reporter.dart
index e795d96..2968ca8 100644
--- a/pkg/test_runner/lib/src/status_reporter.dart
+++ b/pkg/test_runner/lib/src/status_reporter.dart
@@ -108,7 +108,7 @@
 }
 
 void main(List<String> args) {
-  var combinations = _combinations[Platform.operatingSystem];
+  var combinations = _combinations[Platform.operatingSystem]!;
 
   var arches = <String>{};
   var modes = <String>{};
@@ -125,19 +125,15 @@
 
   ensureBuild(modes, arches);
 
-  List<String> keys;
+  List<String>? keys;
   for (var combination in combinations) {
-    for (var mode in combination['modes']) {
-      if (!modes.contains(mode)) {
-        continue;
-      }
+    for (var mode in combination['modes'] as Iterable<String>) {
+      if (!modes.contains(mode)) continue;
 
-      for (var arch in combination['archs']) {
-        if (!arches.contains(arch)) {
-          continue;
-        }
+      for (var arch in combination['archs'] as Iterable<String>) {
+        if (!arches.contains(arch)) continue;
 
-        for (var runtime in combination['runtimes']) {
+        for (var runtime in combination['runtimes'] as Iterable<String>) {
           var compiler = combination['compiler'] as String;
 
           var args = [
@@ -182,9 +178,9 @@
           var values = [compiler, runtime, arch, mode, total];
 
           for (var key in keys) {
-            var value = map[key];
+            var value = map[key]!;
             values.add(value);
-            var pct = 100 * (value / total);
+            var pct = 100 * (value / total!);
             values.add('${pct.toStringAsFixed(3)}%');
           }
 
diff --git a/pkg/test_runner/lib/src/terminal.dart b/pkg/test_runner/lib/src/terminal.dart
index 5aa4421..282ad7c 100644
--- a/pkg/test_runner/lib/src/terminal.dart
+++ b/pkg/test_runner/lib/src/terminal.dart
@@ -58,9 +58,7 @@
 /// other sorts of whitespace or separators.
 ///
 /// If [prefix] is passed, it's added at the beginning of any wrapped lines.
-String wordWrap(String text, {String prefix}) {
-  prefix ??= '';
-
+String wordWrap(String text, {String prefix = ''}) {
   var buffer = StringBuffer();
   var originalLines = text.split('\n');
   var lengthSoFar = 0;
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index 72ed102..66522b5 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -60,8 +60,7 @@
   final TestFile testFile;
 
   TestCase(this.displayName, this.commands, this.configuration,
-      this.expectedOutcomes,
-      {this.testFile}) {
+      this.expectedOutcomes, this.testFile) {
     // A test case should do something.
     assert(commands.isNotEmpty);
   }
@@ -78,15 +77,15 @@
 
   TestCase indexedCopy(int index) {
     var newCommands = commands.map((c) => c.indexedCopy(index)).toList();
-    return TestCase(displayName, newCommands, configuration, expectedOutcomes,
-        testFile: testFile);
+    return TestCase(
+        displayName, newCommands, configuration, expectedOutcomes, testFile);
   }
 
-  bool get hasRuntimeError => testFile?.hasRuntimeError ?? false;
-  bool get hasStaticWarning => testFile?.hasStaticWarning ?? false;
-  bool get hasSyntaxError => testFile?.hasSyntaxError ?? false;
-  bool get hasCompileError => testFile?.hasCompileError ?? false;
-  bool get hasCrash => testFile?.hasCrash ?? false;
+  bool get hasRuntimeError => testFile.hasRuntimeError;
+  bool get hasStaticWarning => testFile.hasStaticWarning;
+  bool get hasSyntaxError => testFile.hasSyntaxError;
+  bool get hasCompileError => testFile.hasCompileError;
+  bool get hasCrash => testFile.hasCrash;
 
   bool get unexpectedOutput {
     var outcome = result;
@@ -129,7 +128,7 @@
           "displayName: '$displayName', "
           "configurationString: '$configurationString')");
     }
-    return commandOutputs[commands[commandOutputs.length - 1]];
+    return commandOutputs[commands[commandOutputs.length - 1]]!;
   }
 
   Command get lastCommandExecuted {
@@ -187,7 +186,7 @@
 /// Helper to get a list of all child pids for a parent process.
 Future<List<int>> _getPidList(int parentId, List<String> diagnostics) async {
   var pids = [parentId];
-  List<String> lines;
+  late List<String> lines;
   var startLine = 0;
   if (io.Platform.isLinux || io.Platform.isMacOS) {
     var result =
@@ -234,17 +233,17 @@
   final ProcessCommand command;
   final int timeout;
   bool timedOut = false;
-  DateTime startTime;
-  int pid;
+  late DateTime startTime;
+  int? pid;
   final OutputLog _stdout;
   final OutputLog _stderr = OutputLog();
   final List<String> diagnostics = [];
   bool compilationSkipped = false;
-  Completer<CommandOutput> completer;
+  late Completer<CommandOutput> completer;
   final TestConfiguration configuration;
 
   RunningProcess(this.command, this.timeout,
-      {this.configuration, io.File outputFile})
+      {required this.configuration, io.File? outputFile})
       : _stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
 
   Future<CommandOutput> run() {
@@ -271,56 +270,54 @@
 
         // Close stdin so that tests that try to block on input will fail.
         process.stdin.close();
-        timeoutHandler() async {
+        FutureOr<int> timeoutHandler() async {
           timedOut = true;
-          if (process != null) {
-            String executable;
-            if (io.Platform.isLinux) {
-              executable = 'eu-stack';
-            } else if (io.Platform.isMacOS) {
-              // Try to print stack traces of the timed out process.
-              // `sample` is a sampling profiler but we ask it sample for 1
-              // second with a 4 second delay between samples so that we only
-              // sample the threads once.
-              executable = '/usr/bin/sample';
-            } else if (io.Platform.isWindows) {
-              var isX64 = command.executable.contains("X64") ||
-                  command.executable.contains("SIMARM64") ||
-                  command.executable.contains("SIMARM64C") ||
-                  command.executable.contains("SIMRISCV64");
-              if (configuration.windowsSdkPath != null) {
-                executable = configuration.windowsSdkPath +
-                    "\\Debuggers\\${isX64 ? 'x64' : 'x86'}\\cdb.exe";
-                diagnostics.add("Using $executable to print stack traces");
-              } else {
-                diagnostics.add("win_sdk_path not found");
-              }
+          String? executable;
+          if (io.Platform.isLinux) {
+            executable = 'eu-stack';
+          } else if (io.Platform.isMacOS) {
+            // Try to print stack traces of the timed out process.
+            // `sample` is a sampling profiler but we ask it sample for 1
+            // second with a 4 second delay between samples so that we only
+            // sample the threads once.
+            executable = '/usr/bin/sample';
+          } else if (io.Platform.isWindows) {
+            var isX64 = command.executable.contains("X64") ||
+                command.executable.contains("SIMARM64") ||
+                command.executable.contains("SIMARM64C") ||
+                command.executable.contains("SIMRISCV64");
+            if (configuration.windowsSdkPath != null) {
+              executable = configuration.windowsSdkPath! +
+                  "\\Debuggers\\${isX64 ? 'x64' : 'x86'}\\cdb.exe";
+              diagnostics.add("Using $executable to print stack traces");
             } else {
-              diagnostics.add("Capturing stack traces on"
-                  "${io.Platform.operatingSystem} not supported");
+              diagnostics.add("win_sdk_path not found");
             }
-            if (executable != null) {
-              var pids = await _getPidList(process.pid, diagnostics);
-              diagnostics.add("Process list including children: $pids");
-              for (pid in pids) {
-                List<String> arguments;
-                if (io.Platform.isLinux) {
-                  arguments = ['-p $pid'];
-                } else if (io.Platform.isMacOS) {
-                  arguments = ['$pid', '1', '4000', '-mayDie'];
-                } else if (io.Platform.isWindows) {
-                  arguments = ['-p', '$pid', '-c', '!uniqstack;qd'];
-                } else {
-                  assert(false);
-                }
-                diagnostics.add("Trying to capture stack trace for pid $pid");
-                try {
-                  var result = await io.Process.run(executable, arguments);
-                  diagnostics.addAll((result.stdout as String).split('\n'));
-                  diagnostics.addAll((result.stderr as String).split('\n'));
-                } catch (error) {
-                  diagnostics.add("Unable to capture stack traces: $error");
-                }
+          } else {
+            diagnostics.add("Capturing stack traces on"
+                "${io.Platform.operatingSystem} not supported");
+          }
+          if (executable != null) {
+            var pids = await _getPidList(process.pid, diagnostics);
+            diagnostics.add("Process list including children: $pids");
+            for (var pid in pids) {
+              late List<String> arguments;
+              if (io.Platform.isLinux) {
+                arguments = ['-p $pid'];
+              } else if (io.Platform.isMacOS) {
+                arguments = ['$pid', '1', '4000', '-mayDie'];
+              } else if (io.Platform.isWindows) {
+                arguments = ['-p', '$pid', '-c', '!uniqstack;qd'];
+              } else {
+                assert(false);
+              }
+              diagnostics.add("Trying to capture stack trace for pid $pid");
+              try {
+                var result = await io.Process.run(executable, arguments);
+                diagnostics.addAll((result.stdout as String).split('\n'));
+                diagnostics.addAll((result.stderr as String).split('\n'));
+              } catch (error) {
+                diagnostics.add("Unable to capture stack traces: $error");
               }
             }
 
@@ -328,6 +325,7 @@
               diagnostics.add("Unable to kill ${process.pid}");
             }
           }
+          return 1;
         }
 
         // Wait for the process to finish or timeout.
@@ -343,7 +341,7 @@
                 "$maxStdioDelayPassedMessage (command: $command)");
             await _stdout.cancel();
             await _stderr.cancel();
-            return null;
+            return [];
           }).then((_) {
             if (_stdout is FileOutputLog) {
               // Prevent logging data that has already been written to a file
@@ -358,6 +356,8 @@
         // TODO(floitsch): should we try to report the stacktrace?
         print("Process error:");
         print("  Command: $command");
+        print("  Executable: ${command.executable}");
+        print("  Working directory: ${command.workingDirectory}");
         print("  Error: $e");
         _commandComplete(-1);
         return true;
@@ -388,7 +388,7 @@
         stderrData,
         DateTime.now().difference(startTime),
         compilationSkipped,
-        pid);
+        pid ?? 0);
     commandOutput.diagnostics.addAll(diagnostics);
     return commandOutput;
   }
@@ -396,10 +396,8 @@
   Map<String, String> _createProcessEnvironment() {
     final environment = Map<String, String>.from(io.Platform.environment);
     environment.addAll(sanitizerEnvironmentVariables);
-    if (command.environmentOverrides != null) {
-      for (var key in command.environmentOverrides.keys) {
-        environment[key] = command.environmentOverrides[key];
-      }
+    for (var entry in command.environmentOverrides.entries) {
+      environment[entry.key] = entry.value;
     }
     for (var excludedEnvironmentVariable in _excludedEnvironmentVariables) {
       environment.remove(excludedEnvironmentVariable);
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index 5c3dddb..50b7337 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -104,12 +104,13 @@
     exit(1);
   }
 
-  var services = <WebDriverService>{};
+  var services = <Future<WebDriverService>>{};
   for (var configuration in configurations) {
     if (!listTests && !listStatusFiles && runningBrowserTests) {
       serverFutures.add(configuration.startServers());
       if (WebDriverService.supportedRuntimes.contains(configuration.runtime)) {
-        services.add(WebDriverService.fromRuntime(configuration.runtime));
+        services.add(
+            WebDriverService.startServiceForRuntime(configuration.runtime));
       }
     }
 
@@ -132,11 +133,14 @@
       // Issue: https://github.com/dart-lang/sdk/issues/23891
       // This change does not fix the problem.
       maxBrowserProcesses = math.max(1, maxBrowserProcesses ~/ 2);
+    } else if (configuration.runtime == Runtime.chromeOnAndroid) {
+      maxBrowserProcesses =
+          math.min(maxBrowserProcesses, (await AdbHelper.listDevices()).length);
     }
 
     // If we specifically pass in a suite only run that.
     if (configuration.suiteDirectory != null) {
-      var suitePath = Path(configuration.suiteDirectory);
+      var suitePath = Path(configuration.suiteDirectory!);
       testSuites.add(PackageTestSuite(configuration, suitePath));
     } else {
       for (var testSuiteDir in testSuiteDirectories) {
@@ -178,8 +182,8 @@
   }
 
   for (var service in services) {
-    serverFutures.add(service.start());
-    eventListeners.add(service);
+    serverFutures.add(service);
+    service.then(eventListeners.add);
   }
 
   // If we only need to print out status files for test suites
@@ -265,7 +269,7 @@
 
   // If any of the configurations need to access android devices we'll first
   // make a pool of all available adb devices.
-  AdbDevicePool adbDevicePool;
+  AdbDevicePool? adbDevicePool;
   var needsAdbDevicePool = configurations.any((conf) {
     return conf.system == System.android;
   });
diff --git a/pkg/test_runner/lib/src/test_file.dart b/pkg/test_runner/lib/src/test_file.dart
index b39ba90..ba2d361 100644
--- a/pkg/test_runner/lib/src/test_file.dart
+++ b/pkg/test_runner/lib/src/test_file.dart
@@ -27,7 +27,7 @@
 
   var options = <T>[];
   for (var match in matches) {
-    for (var option in _splitWords(match[1])) {
+    for (var option in _splitWords(match[1]!)) {
       options.add(convert(option));
     }
   }
@@ -40,9 +40,12 @@
     _parseOption<String>(filePath, contents, name, (string) => string,
         allowMultiple: allowMultiple);
 
+// Fake path used as sentinel for test files that don't have a path.
+final _fakePath = Path('/fake');
+
 abstract class _TestFileBase {
   /// The test suite directory containing this test.
-  final Path _suiteDirectory;
+  final Path? _suiteDirectory;
 
   /// The full path to the test file.
   final Path path;
@@ -92,14 +95,14 @@
     // directory or path. Don't crash in that case.
     // TODO(rnystrom): Is there a cleaner solution? Should we use the C++ file
     // as the path for the TestFile?
-    if (originPath == null) return 0;
+    if (originPath == _fakePath) return 0;
 
-    return originPath.relativeTo(_suiteDirectory).toString().hashCode;
+    return originPath.relativeTo(_suiteDirectory!).toString().hashCode;
   }
 
   _TestFileBase(this._suiteDirectory, this.path, this.expectedErrors) {
     // The VM C++ unit tests have a special fake TestFile with no path.
-    if (path != null) assert(path.isAbsolute);
+    assert(path.isAbsolute);
   }
 
   /// The logical name of the test.
@@ -108,7 +111,7 @@
   /// minus any file extension. If this test was split from a multitest,
   /// it contains the multitest key.
   String get name {
-    var testNamePath = originPath.relativeTo(_suiteDirectory);
+    var testNamePath = originPath.relativeTo(_suiteDirectory!);
     var directory = testNamePath.directoryPath;
     var filenameWithoutExt = testNamePath.filenameWithoutExtension;
 
@@ -198,7 +201,9 @@
           hasCrash: false,
           isMultitest: false,
           sharedObjects: [],
-          otherResources: []);
+          otherResources: [],
+          environment: {},
+          experiments: []);
     }
 
     // Required features.
@@ -217,7 +222,7 @@
     var vmOptions = <List<String>>[];
     var matches = _vmOptionsRegExp.allMatches(contents);
     for (var match in matches) {
-      vmOptions.add(_splitWords(match[1]));
+      vmOptions.add(_splitWords(match[1]!));
     }
     if (vmOptions.isEmpty) vmOptions.add(<String>[]);
 
@@ -249,26 +254,25 @@
               "flags. Was:\n$sharedOption");
         }
 
-        experiments.addAll(match.group(1).split(","));
+        experiments.addAll(match.group(1)!.split(","));
         sharedOptions.removeAt(i);
         i--;
       }
     }
 
     // Environment.
-    Map<String, String> environment;
+    var environment = <String, String>{};
     matches = _environmentRegExp.allMatches(contents);
     for (var match in matches) {
-      var envDef = match[1];
+      var envDef = match[1]!;
       var pos = envDef.indexOf('=');
       var name = (pos < 0) ? envDef : envDef.substring(0, pos);
       var value = (pos < 0) ? '' : envDef.substring(pos + 1);
-      environment ??= {};
       environment[name] = value;
     }
 
     // Packages.
-    String packages;
+    String? packages;
 
     matches = _packagesRegExp.allMatches(contents);
     for (var match in matches) {
@@ -280,7 +284,7 @@
         // Packages=none means that no packages option should be given. Any
         // other value overrides packages.
         packages =
-            Uri.file(filePath).resolveUri(Uri.file(packages)).toFilePath();
+            Uri.file(filePath).resolveUri(Uri.file(packages!)).toFilePath();
       }
     }
 
@@ -343,13 +347,13 @@
 
   /// A special fake test file for representing a VM unit test written in C++.
   TestFile.vmUnitTest(
-      {this.hasSyntaxError,
-      this.hasCompileError,
-      this.hasRuntimeError,
-      this.hasStaticWarning,
-      this.hasCrash})
+      {required this.hasSyntaxError,
+      required this.hasCompileError,
+      required this.hasRuntimeError,
+      required this.hasStaticWarning,
+      required this.hasCrash})
       : packages = null,
-        environment = null,
+        environment = {},
         isMultitest = false,
         requirements = [],
         sharedOptions = [],
@@ -361,26 +365,26 @@
         otherResources = [],
         experiments = [],
         isVmIntermediateLanguageTest = false,
-        super(null, null, []);
+        super(null, _fakePath, []);
 
   TestFile._(Path suiteDirectory, Path path, List<StaticError> expectedErrors,
       {this.packages,
-      this.environment,
-      this.isMultitest,
-      this.hasSyntaxError,
-      this.hasCompileError,
-      this.hasRuntimeError,
-      this.hasStaticWarning,
-      this.hasCrash,
-      this.requirements,
-      this.sharedOptions,
-      this.dartOptions,
-      this.dart2jsOptions,
-      this.ddcOptions,
-      this.vmOptions,
-      this.sharedObjects,
-      this.otherResources,
-      this.experiments,
+      required this.environment,
+      required this.isMultitest,
+      required this.hasSyntaxError,
+      required this.hasCompileError,
+      required this.hasRuntimeError,
+      required this.hasStaticWarning,
+      required this.hasCrash,
+      required this.requirements,
+      required this.sharedOptions,
+      required this.dartOptions,
+      required this.dart2jsOptions,
+      required this.ddcOptions,
+      required this.vmOptions,
+      required this.sharedObjects,
+      required this.otherResources,
+      required this.experiments,
       this.isVmIntermediateLanguageTest = false})
       : super(suiteDirectory, path, expectedErrors) {
     assert(!isMultitest || dartOptions.isEmpty);
@@ -390,7 +394,7 @@
 
   String get multitestKey => "";
 
-  final String packages;
+  final String? packages;
 
   final Map<String, String> environment;
 
@@ -427,16 +431,16 @@
   /// Derive a multitest test section file from this multitest file with the
   /// given [multitestKey] and expectations.
   TestFile split(Path path, String multitestKey, String contents,
-          {bool hasCompileError,
-          bool hasRuntimeError,
-          bool hasStaticWarning,
-          bool hasSyntaxError}) =>
+          {bool hasCompileError = false,
+          bool hasRuntimeError = false,
+          bool hasStaticWarning = false,
+          bool hasSyntaxError = false}) =>
       _MultitestFile(
           this, path, multitestKey, StaticError.parseExpectations(contents),
-          hasCompileError: hasCompileError ?? false,
-          hasRuntimeError: hasRuntimeError ?? false,
-          hasStaticWarning: hasStaticWarning ?? false,
-          hasSyntaxError: hasSyntaxError ?? false);
+          hasCompileError: hasCompileError,
+          hasRuntimeError: hasRuntimeError,
+          hasStaticWarning: hasStaticWarning,
+          hasSyntaxError: hasSyntaxError);
 
   String toString() => """TestFile(
   packages: $packages
@@ -478,15 +482,15 @@
 
   _MultitestFile(this._origin, Path path, this.multitestKey,
       List<StaticError> expectedErrors,
-      {this.hasCompileError,
-      this.hasRuntimeError,
-      this.hasStaticWarning,
-      this.hasSyntaxError})
+      {required this.hasCompileError,
+      required this.hasRuntimeError,
+      required this.hasStaticWarning,
+      required this.hasSyntaxError})
       : super(_origin._suiteDirectory, path, expectedErrors);
 
   Path get originPath => _origin.path;
 
-  String get packages => _origin.packages;
+  String? get packages => _origin.packages;
 
   List<Feature> get requirements => _origin.requirements;
   List<String> get dart2jsOptions => _origin.dart2jsOptions;
@@ -503,10 +507,10 @@
   List<List<String>> get vmOptions => _origin.vmOptions;
 
   TestFile split(Path path, String multitestKey, String contents,
-          {bool hasCompileError,
-          bool hasRuntimeError,
-          bool hasStaticWarning,
-          bool hasSyntaxError}) =>
+          {bool hasCompileError = false,
+          bool hasRuntimeError = false,
+          bool hasStaticWarning = false,
+          bool hasSyntaxError = false}) =>
       throw UnsupportedError(
           "Can't derive a test from one already derived from a multitest.");
 }
diff --git a/pkg/test_runner/lib/src/test_progress.dart b/pkg/test_runner/lib/src/test_progress.dart
index 8d01e3d..8444cbb 100644
--- a/pkg/test_runner/lib/src/test_progress.dart
+++ b/pkg/test_runner/lib/src/test_progress.dart
@@ -74,7 +74,7 @@
   int _numTests = 0;
   int _numCompleted = 0;
   bool _allKnown = false;
-  Timer _timer;
+  late Timer _timer;
 
   TimedProgressPrinter() {
     _timer = Timer.periodic(interval, callback);
@@ -180,7 +180,7 @@
         }
 
         // We have found and copied the binary.
-        RandomAccessFile unexpectedCrashesFile;
+        RandomAccessFile? unexpectedCrashesFile;
         try {
           unexpectedCrashesFile =
               File('unexpected-crashes').openSync(mode: FileMode.append);
@@ -205,7 +205,7 @@
 class SummaryPrinter extends EventListener {
   final bool jsonOnly;
 
-  SummaryPrinter({bool jsonOnly}) : jsonOnly = jsonOnly ?? false;
+  SummaryPrinter({this.jsonOnly = false});
 
   void allTestsKnown() {
     if (jsonOnly) {
@@ -228,8 +228,7 @@
     for (var commandOutput in test.commandOutputs.values) {
       var command = commandOutput.command;
       _commandOutputs.add(commandOutput);
-      _commandToTestCases.putIfAbsent(command, () => <TestCase>[]);
-      _commandToTestCases[command].add(test);
+      _commandToTestCases.putIfAbsent(command, () => <TestCase>[]).add(test);
     }
   }
 
@@ -240,10 +239,9 @@
     outputs.sort((a, b) {
       return b.time.inMilliseconds - a.time.inMilliseconds;
     });
-    for (var i = 0; i < 20 && i < outputs.length; i++) {
-      var commandOutput = outputs[i];
+    for (var commandOutput in outputs.take(20)) {
       var command = commandOutput.command;
-      var testCases = _commandToTestCases[command];
+      var testCases = _commandToTestCases[command]!;
 
       var testCasesDescription = testCases.map((testCase) {
         return "${testCase.configurationString}/${testCase.displayName}";
@@ -381,7 +379,7 @@
 
   ProgressIndicator(this._startTime);
 
-  static EventListener fromProgress(
+  static EventListener? fromProgress(
       Progress progress, DateTime startTime, Formatter formatter) {
     switch (progress) {
       case Progress.compact:
@@ -461,7 +459,7 @@
 }
 
 class BuildbotProgressIndicator extends ProgressIndicator {
-  static String stepName;
+  static String? stepName;
 
   BuildbotProgressIndicator(DateTime startTime) : super(startTime);
 
@@ -493,9 +491,9 @@
 /// Builds and formats the failure output for a failed test.
 class OutputWriter {
   final Formatter _formatter;
-  final List<String> _lines;
-  String _pendingSection;
-  String _pendingSubsection;
+  final List<String?> _lines;
+  String? _pendingSection;
+  String? _pendingSubsection;
   bool _pendingLine = false;
 
   OutputWriter(this._formatter, this._lines);
@@ -511,7 +509,7 @@
     _pendingLine = false;
   }
 
-  void write(String line) {
+  void write(String? line) {
     _writePending();
     _lines.add(line);
   }
@@ -654,8 +652,8 @@
     var index = name.indexOf('/');
     var suite = name.substring(0, index);
     var testName = name.substring(index + 1);
-    var time =
-        test.commandOutputs.values.fold(Duration.zero, (d, o) => d + o.time);
+    var time = test.commandOutputs.values
+        .fold<Duration>(Duration.zero, (d, o) => d + o.time);
     var experiments = test.experiments;
     var record = {
       "name": name,
@@ -686,7 +684,6 @@
   }
 
   void writeOutputFile(List<Map> results, String fileName) {
-    if (_outputDirectory == null) return;
     var path = Uri.directory(_outputDirectory).resolve(fileName);
     File.fromUri(path)
         .writeAsStringSync(newlineTerminated(results.map(jsonEncode)));
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index 818acd7..1d48e10 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -14,6 +14,7 @@
 import 'dart:math';
 
 import "package:status_file/expectation.dart";
+import 'package:test_runner/src/compiler_configuration.dart';
 
 import 'browser.dart';
 import 'command.dart';
@@ -32,11 +33,11 @@
 typedef TestCaseEvent = void Function(TestCase testCase);
 
 typedef CreateTest = void Function(Path filePath, Path originTestPath,
-    {bool hasSyntaxError,
-    bool hasCompileError,
-    bool hasRuntimeError,
-    bool hasStaticWarning,
-    String multitestKey});
+    {bool? hasSyntaxError,
+    bool? hasCompileError,
+    bool? hasRuntimeError,
+    bool? hasStaticWarning,
+    String? multitestKey});
 
 typedef VoidFunction = void Function();
 
@@ -51,22 +52,23 @@
   final List<String> statusFilePaths;
 
   /// This function is set by subclasses before enqueueing starts.
-  Map<String, String> _environmentOverrides;
+  final Map<String, String> _environmentOverrides;
 
-  TestSuite(this.configuration, this.suiteName, this.statusFilePaths) {
-    _environmentOverrides = {
-      'DART_CONFIGURATION': configuration.configurationDirectory,
-      if (Platform.isWindows) 'DART_SUPPRESS_WER': '1',
-      if (Platform.isWindows && configuration.copyCoreDumps)
-        'DART_CRASHPAD_HANDLER':
-            Uri.base.resolve(buildDir + '/crashpad_handler.exe').toFilePath(),
-      if (configuration.chromePath != null)
-        'CHROME_PATH': Uri.base.resolve(configuration.chromePath).toFilePath(),
-      if (configuration.firefoxPath != null)
-        'FIREFOX_PATH':
-            Uri.base.resolve(configuration.firefoxPath).toFilePath(),
-    };
-  }
+  TestSuite(this.configuration, this.suiteName, this.statusFilePaths)
+      : _environmentOverrides = {
+          'DART_CONFIGURATION': configuration.configurationDirectory,
+          if (Platform.isWindows) 'DART_SUPPRESS_WER': '1',
+          if (Platform.isWindows && configuration.copyCoreDumps)
+            'DART_CRASHPAD_HANDLER': Uri.base
+                .resolve(configuration.buildDirectory + '/crashpad_handler.exe')
+                .toFilePath(),
+          if (configuration.chromePath != null)
+            'CHROME_PATH':
+                Uri.base.resolve(configuration.chromePath!).toFilePath(),
+          if (configuration.firefoxPath != null)
+            'FIREFOX_PATH':
+                Uri.base.resolve(configuration.firefoxPath!).toFilePath(),
+        };
 
   Map<String, String> get environmentOverrides => _environmentOverrides;
 
@@ -75,7 +77,7 @@
 
   /// The path to the compiler for this suite's configuration. Returns `null` if
   /// no compiler should be used.
-  String get compilerPath {
+  String? get compilerPath {
     var compilerConfiguration = configuration.compilerConfiguration;
     if (!compilerConfiguration.hasCompiler) return null;
     var name = compilerConfiguration.computeCompilerPath();
@@ -117,8 +119,8 @@
       if (expectations.isEmpty) expectations.add(Expectation.pass);
     }
 
-    var testCase = TestCase(displayName, commands, configuration, expectations,
-        testFile: testFile);
+    var testCase =
+        TestCase(displayName, commands, configuration, expectations, testFile);
 
     // Update Summary report.
     if (configuration.printReport) {
@@ -138,13 +140,13 @@
   bool _isRelevantTest(
       TestFile testFile, String displayName, Set<Expectation> expectations) {
     // Test if the selector includes this test.
-    var pattern = configuration.selectors[suiteName];
+    var pattern = configuration.selectors[suiteName]!;
     if (!pattern.hasMatch(displayName)) {
       return false;
     }
 
     if (configuration.testList != null &&
-        !configuration.testList.contains(displayName)) {
+        !configuration.testList!.contains(displayName)) {
       return false;
     }
 
@@ -250,10 +252,10 @@
 /// The executable lists its tests when run with the --list command line flag.
 /// Individual tests are run by specifying them on the command line.
 class VMTestSuite extends TestSuite {
-  String targetRunnerPath;
-  String hostRunnerPath;
-  List<String> initialHostArguments;
-  List<String> initialTargetArguments;
+  late String targetRunnerPath;
+  late String hostRunnerPath;
+  final initialHostArguments = <String>[];
+  final initialTargetArguments = <String>[];
   final String dartDir;
 
   VMTestSuite(TestConfiguration configuration)
@@ -273,10 +275,8 @@
       hostRunnerPath = targetRunnerPath;
     }
 
-    initialHostArguments = <String>[];
-    initialTargetArguments = <String>[];
     if (configuration.useQemu) {
-      final config = QemuConfig.all[configuration.architecture];
+      final config = QemuConfig.all[configuration.architecture]!;
       initialHostArguments.insert(0, hostRunnerPath);
       initialHostArguments.insertAll(0, config.arguments);
       initialTargetArguments.insert(0, targetRunnerPath);
@@ -381,7 +381,7 @@
 /// An executable lists its tests when run with the --list command line flag.
 /// Individual tests are run by specifying them on the command line.
 class FfiTestSuite extends TestSuite {
-  Map<String, String> runnerPaths;
+  late Map<String, String> runnerPaths;
   final String dartDir;
 
   static const targetAbis = [
@@ -504,9 +504,9 @@
   final Path dartDir;
   final bool listRecursively;
   final List<String> extraVmOptions;
-  List<Uri> _dart2JsBootstrapDependencies;
-  Set<String> _testListPossibleFilenames;
-  RegExp _selectorFilenameRegExp;
+  List<Uri>? _dart2JsBootstrapDependencies;
+  Set<String>? _testListPossibleFilenames;
+  late RegExp _selectorFilenameRegExp;
 
   StandardTestSuite(TestConfiguration configuration, String suiteName,
       Path suiteDirectory, List<String> statusFilePaths,
@@ -530,10 +530,10 @@
     // Initialize _testListPossibleFilenames.
     if (configuration.testList != null) {
       _testListPossibleFilenames = <String>{};
-      for (var s in configuration.testList) {
+      for (var s in configuration.testList!) {
         if (s.startsWith("$suiteName/")) {
           s = s.substring(s.indexOf('/') + 1);
-          _testListPossibleFilenames
+          _testListPossibleFilenames!
               .add(suiteDir.append('$s.dart').toNativePath());
           // If the test is a multitest, the filename doesn't include the label.
           // Also if it has multiple VMOptions.  If both, remove two labels.
@@ -541,7 +541,7 @@
             // Twice.
             if (s.lastIndexOf('/') != -1) {
               s = s.substring(0, s.lastIndexOf('/'));
-              _testListPossibleFilenames
+              _testListPossibleFilenames!
                   .add(suiteDir.append('$s.dart').toNativePath());
             }
           }
@@ -550,7 +550,7 @@
     }
 
     // Initialize _selectorFilenameRegExp.
-    var pattern = configuration.selectors[suiteName].pattern;
+    var pattern = configuration.selectors[suiteName]!.pattern;
     if (pattern.contains("/")) {
       var lastPart = pattern.substring(pattern.lastIndexOf("/") + 1);
       // If the selector is a multitest name ending in a number or 'none'
@@ -609,13 +609,13 @@
         recursive: true);
   }
 
-  List<Uri> get dart2JsBootstrapDependencies => _dart2JsBootstrapDependencies;
+  List<Uri>? get dart2JsBootstrapDependencies => _dart2JsBootstrapDependencies;
 
   /// The default implementation assumes a file is a test if
   /// it ends in "_test.dart".
   bool isTestFile(String filename) => filename.endsWith("_test.dart");
 
-  List<String> additionalOptions(Path filePath) => [];
+  List<String> additionalOptions(Path? filePath) => [];
 
   void findTestCases(
       TestCaseEvent onTest, Map<String, List<TestFile>> testCache) {
@@ -658,10 +658,11 @@
   }
 
   /// Looks for test files in [directory].
-  Iterable<TestFile> _searchDirectory(Directory directory) sync* {
-    for (var entry in directory.listSync(recursive: listRecursively)) {
-      if (entry is File) yield* _processFile(entry.path);
-    }
+  Iterable<TestFile> _searchDirectory(Directory directory) {
+    return directory
+        .listSync(recursive: listRecursively)
+        .whereType<File>()
+        .expand((file) => _processFile(file.path));
   }
 
   /// Gets the set of [TestFile]s based on the source file at [filePath].
@@ -795,6 +796,7 @@
 
     var compileTimeArguments = <String>[];
     String tempDir;
+    CommandArtifact? compilationArtifact;
     if (compilerConfiguration.hasCompiler) {
       compileTimeArguments = compilerConfiguration.computeCompilerArguments(
           testFile, vmOptions, args);
@@ -812,12 +814,11 @@
         File('$tempDir/$name').createSync(recursive: true);
         File(fromPath.toNativePath()).copySync('$tempDir/$name');
       }
+      compilationArtifact = compilerConfiguration.computeCompilationArtifact(
+          tempDir, compileTimeArguments, environmentOverrides);
+      commands.addAll(compilationArtifact.commands);
     }
 
-    var compilationArtifact = compilerConfiguration.computeCompilationArtifact(
-        tempDir, compileTimeArguments, environmentOverrides);
-    commands.addAll(compilationArtifact.commands);
-
     if ((testFile.hasCompileError || testFile.isStaticErrorTest) &&
         compilerConfiguration.hasCompiler &&
         !compilerConfiguration.runRuntimeDespiteMissingCompileTimeError) {
@@ -838,7 +839,7 @@
         args,
         compilationArtifact);
 
-    var environment = {...environmentOverrides, ...?testFile.environment};
+    var environment = {...environmentOverrides, ...testFile.environment};
 
     return commands
       ..addAll(configuration.runtimeConfiguration.computeRuntimeCommands(
@@ -960,7 +961,7 @@
     assert(supportedCompilers.contains(configuration.compiler));
 
     var args = configuration.compilerConfiguration
-        .computeCompilerArguments(testFile, null, commonArguments);
+        .computeCompilerArguments(testFile, const [], commonArguments);
     var compilation = configuration.compilerConfiguration
         .computeCompilationArtifact(outputDir, args, environmentOverrides);
     commands.addAll(compilation.commands);
@@ -1007,19 +1008,15 @@
     return args;
   }
 
-  String packagesArgument(String packages) {
+  String? packagesArgument(String? packages) {
     // If this test is inside a package, we will check if there is a
     // pubspec.yaml file and if so, create a custom package root for it.
-    if (packages == null && configuration.packages != null) {
-      packages = Path(configuration.packages).toNativePath();
-    }
+    packages ??= Path(configuration.packages).toNativePath();
 
     if (packages == 'none') {
       return null;
-    } else if (packages != null) {
-      return '--packages=$packages';
     } else {
-      return null;
+      return '--packages=$packages';
     }
   }
 
@@ -1076,7 +1073,7 @@
       : super(configuration, 'analyze_library', _libraryPath(configuration),
             ['tests/lib_2/analyzer/analyze_library.status']);
 
-  List<String> additionalOptions(Path filePath, {bool showSdkWarnings}) =>
+  List<String> additionalOptions(Path? filePath, {bool? showSdkWarnings}) =>
       const ['--fatal-warnings', '--fatal-type-errors', '--sdk-warnings'];
 
   Iterable<TestFile> findTests() {
diff --git a/pkg/test_runner/lib/src/testing_servers.dart b/pkg/test_runner/lib/src/testing_servers.dart
index d2fb748..6f86bd4 100644
--- a/pkg/test_runner/lib/src/testing_servers.dart
+++ b/pkg/test_runner/lib/src/testing_servers.dart
@@ -30,7 +30,7 @@
     // handler.  Otherwise, run the notFound handler.
     for (var prefix in _handlers.keys) {
       if (request.uri.path.startsWith(prefix)) {
-        _handlers[prefix](request);
+        _handlers[prefix]!(request);
         return;
       }
     }
@@ -77,16 +77,18 @@
   final Uri _buildDirectory;
   final Uri _dartDirectory;
   final Uri _packages;
-  PackageConfig _packageConfig;
+  late PackageConfig _packageConfig;
   final bool useContentSecurityPolicy;
   final Runtime runtime;
-  DispatchingServer _server;
+  DispatchingServer? _server;
 
   TestingServers._(this.useContentSecurityPolicy, this._buildDirectory,
       this._dartDirectory, this._packages, this.runtime);
 
   factory TestingServers(String buildDirectory, bool useContentSecurityPolicy,
-      [Runtime runtime = Runtime.none, String dartDirectory, String packages]) {
+      [Runtime runtime = Runtime.none,
+      String? dartDirectory,
+      String? packages]) {
     var buildDirectoryUri = Uri.base.resolveUri(Uri.directory(buildDirectory));
     var dartDirectoryUri = dartDirectory == null
         ? Repository.uri
@@ -104,7 +106,7 @@
 
   int get crossOriginPort => _serverList[1].port;
 
-  DispatchingServer get server => _server;
+  DispatchingServer? get server => _server;
 
   /// [startServers] will start two Http servers.
   ///
@@ -241,7 +243,7 @@
 
   void _handleUploadRequest(HttpRequest request) async {
     try {
-      var builder = await request.fold(BytesBuilder(), (var b, var d) {
+      var builder = await request.fold(BytesBuilder(), (dynamic b, var d) {
         b.add(d);
         return b;
       });
@@ -256,7 +258,7 @@
     }
   }
 
-  Uri _getFileUriFromRequestUri(Uri request) {
+  Uri? _getFileUriFromRequestUri(Uri request) {
     // Go to the top of the file to see an explanation of the URL path scheme.
     var pathSegments = request.normalizePath().pathSegments;
     if (pathSegments.isEmpty) return null;
diff --git a/pkg/test_runner/lib/src/update_errors.dart b/pkg/test_runner/lib/src/update_errors.dart
index b4b53ef..d0640df 100644
--- a/pkg/test_runner/lib/src/update_errors.dart
+++ b/pkg/test_runner/lib/src/update_errors.dart
@@ -12,13 +12,11 @@
 /// Removes existing static error marker comments in [source] and adds markers
 /// for the given [errors].
 ///
-/// If [remove] is not `null`, then only removes existing errors for the given
+/// If [remove] is not empty, then only removes existing errors for the given
 /// sources. If [includeContext] is `true`, then includes context messages in
 /// the output. Otherwise discards them.
 String updateErrorExpectations(String source, List<StaticError> errors,
-    {Set<ErrorSource> remove, bool includeContext = false}) {
-  remove ??= {};
-
+    {Set<ErrorSource> remove = const {}, bool includeContext = false}) {
   // Split the existing errors into kept and deleted lists.
   var existingErrors = StaticError.parseExpectations(source);
   var keptErrors = <StaticError>[];
@@ -31,7 +29,7 @@
     }
   }
 
-  var lines = source.split("\n");
+  List<String?> lines = source.split("\n");
 
   // Keep track of the indentation on any existing expectation markers. If
   // found, it will try to preserve that indentation.
@@ -43,7 +41,7 @@
   void removeLine(int line) {
     if (lines[line] == null) return;
 
-    indentation[line] = _countIndentation(lines[line]);
+    indentation[line] = _countIndentation(lines[line]!);
 
     // Null the line instead of removing it so that line numbers in the
     // reported errors are still correct.
@@ -85,12 +83,12 @@
 
   // Rebuild the source file a line at a time.
   var previousIndent = 0;
-  var result = <String>[];
+  var result = <String?>[];
   for (var i = 0; i < lines.length; i++) {
     // Keep the code.
     if (lines[i] != null) {
       result.add(lines[i]);
-      previousIndent = _countIndentation(lines[i]);
+      previousIndent = _countIndentation(lines[i]!);
     }
 
     // Add expectations for any errors reported on this line.
@@ -113,13 +111,13 @@
       // Write the location line, unless we already have an identical one. Allow
       // sharing locations between errors with and without explicit lengths.
       if (error.column != previousColumn ||
-          (previousLength != null &&
-              error.length != null &&
+          (previousLength != 0 &&
+              error.length != 0 &&
               error.length != previousLength)) {
         // If the error can't fit in a line comment, or no source location is
         // specified, use an explicit location.
         if (error.column <= 2 || error.length == 0) {
-          if (error.length == null) {
+          if (error.length == 0) {
             result.add("$comment [error column "
                 "${error.column}]");
           } else {
@@ -129,7 +127,7 @@
         } else {
           var spacing = " " * (error.column - 1 - 2 - indent);
           // A CFE-only error may not have a length, so treat it as length 1.
-          var carets = "^" * (error.length ?? 1);
+          var carets = "^" * (error.length == 0 ? 1 : error.length);
           result.add("$comment$spacing$carets");
         }
       }
@@ -155,7 +153,7 @@
       // line.
       if (i < lines.length - 1 &&
           lines[i + 1] != null &&
-          _lineCommentRegExp.hasMatch(lines[i + 1])) {
+          _lineCommentRegExp.hasMatch(lines[i + 1]!)) {
         result.add("");
       }
     }
@@ -189,6 +187,6 @@
 
 /// Returns the number of characters of leading spaces in [line].
 int _countIndentation(String line) {
-  var match = _indentationRegExp.firstMatch(line);
-  return match.group(1).length;
+  var match = _indentationRegExp.firstMatch(line)!;
+  return match.group(1)!.length;
 }
diff --git a/pkg/test_runner/lib/src/utils.dart b/pkg/test_runner/lib/src/utils.dart
index 03d3f84..125c224 100644
--- a/pkg/test_runner/lib/src/utils.dart
+++ b/pkg/test_runner/lib/src/utils.dart
@@ -33,10 +33,10 @@
 String get executableExtension => Platform.isWindows ? '.exe' : '';
 
 class DebugLogger {
-  static IOSink _sink;
+  static IOSink? _sink;
 
   /// If [path] was null, the DebugLogger will write messages to stdout.
-  static void init(Path path) {
+  static void init(Path? path) {
     if (path != null) {
       _sink = File(path.toNativePath()).openWrite(mode: FileMode.append);
     }
@@ -44,7 +44,7 @@
 
   static void close() {
     if (_sink != null) {
-      _sink.close();
+      _sink!.close();
       _sink = null;
     }
   }
@@ -75,7 +75,7 @@
 
   static void _print(String msg) {
     if (_sink != null) {
-      _sink.writeln(msg);
+      _sink!.writeln(msg);
     } else {
       print(msg);
     }
@@ -84,98 +84,6 @@
   static String get _datetime => "${DateTime.now()}";
 }
 
-String prettifyJson(Object json,
-    {int startIndentation = 0, int shiftWidth = 6}) {
-  var currentIndentation = startIndentation;
-  var buffer = StringBuffer();
-
-  String indentationString() {
-    return List.filled(currentIndentation, ' ').join('');
-  }
-
-  addString(String s, {bool indentation = true, bool newLine = true}) {
-    if (indentation) {
-      buffer.write(indentationString());
-    }
-    buffer.write(s.replaceAll("\n", "\n${indentationString()}"));
-    if (newLine) buffer.write("\n");
-  }
-
-  prettifyJsonInternal(Object obj,
-      {bool indentation = true, bool newLine = true}) {
-    if (obj is List) {
-      addString("[", indentation: indentation);
-      currentIndentation += shiftWidth;
-      for (var item in obj) {
-        prettifyJsonInternal(item, indentation: indentation, newLine: false);
-        addString(",", indentation: false);
-      }
-      currentIndentation -= shiftWidth;
-      addString("]", indentation: indentation);
-    } else if (obj is Map) {
-      addString("{", indentation: indentation);
-      currentIndentation += shiftWidth;
-      for (var key in obj.keys) {
-        addString("$key: ", indentation: indentation, newLine: false);
-        currentIndentation += shiftWidth;
-        prettifyJsonInternal(obj[key], indentation: false);
-        currentIndentation -= shiftWidth;
-      }
-      currentIndentation -= shiftWidth;
-      addString("}", indentation: indentation, newLine: newLine);
-    } else {
-      addString("$obj", indentation: indentation, newLine: newLine);
-    }
-  }
-
-  prettifyJsonInternal(json);
-  return buffer.toString();
-}
-
-/// Compares a range of bytes from [buffer1] with a range of bytes from
-/// [buffer2].
-///
-/// Returns `true` if the [count] bytes in [buffer1] (starting at [offset1])
-/// match the [count] bytes in [buffer2] (starting at [offset2]).
-bool areByteArraysEqual(
-    List<int> buffer1, int offset1, List<int> buffer2, int offset2, int count) {
-  if ((offset1 + count) > buffer1.length ||
-      (offset2 + count) > buffer2.length) {
-    return false;
-  }
-
-  for (var i = 0; i < count; i++) {
-    if (buffer1[offset1 + i] != buffer2[offset2 + i]) {
-      return false;
-    }
-  }
-  return true;
-}
-
-/// Searches for [pattern] in [data] beginning at [startPos].
-///
-/// Returns `true` if [pattern] was found in [data].
-int findBytes(List<int> data, List<int> pattern, [int startPos = 0]) {
-  // TODO(kustermann): Use one of the fast string-matching algorithms!
-  for (var i = startPos; i < (data.length - pattern.length); i++) {
-    var found = true;
-    for (var j = 0; j < pattern.length; j++) {
-      if (data[i + j] != pattern[j]) {
-        found = false;
-        break;
-      }
-    }
-    if (found) {
-      return i;
-    }
-  }
-  return -1;
-}
-
-List<int> encodeUtf8(String string) {
-  return utf8.encode(string);
-}
-
 // TODO(kustermann,ricow): As soon we have a debug log we should log
 // invalid utf8-encoded input to the log.
 // Currently invalid bytes will be replaced by a replacement character.
@@ -237,11 +145,11 @@
 class HashCodeBuilder {
   int _value = 0;
 
-  void add(Object object) {
+  void add(Object? object) {
     _value = ((_value * 31) ^ object.hashCode) & 0x3FFFFFFF;
   }
 
-  void addJson(Object object) {
+  void addJson(Object? object) {
     if (object == null ||
         object is num ||
         object is String ||
@@ -264,7 +172,7 @@
   int get value => _value;
 }
 
-bool deepJsonCompare(Object a, Object b) {
+bool deepJsonCompare(Object? a, Object? b) {
   if (a == null || a is num || a is String || a is Uri) {
     return a == b;
   } else if (a is List) {
@@ -295,7 +203,7 @@
 }
 
 class LastModifiedCache {
-  final Map<String, DateTime> _cache = {};
+  final Map<String, DateTime?> _cache = {};
 
   /// Returns the last modified date of the given [uri].
   ///
@@ -305,7 +213,7 @@
   ///
   /// In case [uri] is not a local file, this method will always return
   /// the current date.
-  DateTime getLastModified(Uri uri) {
+  DateTime? getLastModified(Uri uri) {
     if (uri.isScheme("file")) {
       if (_cache.containsKey(uri.path)) {
         return _cache[uri.path];
@@ -325,10 +233,7 @@
   ///
   /// The information will be cached.
   bool doesFileExist(String path) {
-    if (!_cache.containsKey(path)) {
-      _cache[path] = File(path).existsSync();
-    }
-    return _cache[path];
+    return _cache.putIfAbsent(path, () => File(path).existsSync());
   }
 }
 
@@ -507,9 +412,9 @@
     var windowsPathEndLength = 30;
     if (Platform.operatingSystem == 'windows' &&
         path.length > windowsShortenPathLimit) {
-      for (var key in pathReplacements.keys) {
-        if (path.startsWith(key)) {
-          path = path.replaceFirst(key, pathReplacements[key]);
+      for (var entry in pathReplacements.entries) {
+        if (path.startsWith(entry.key)) {
+          path = path.replaceFirst(entry.key, entry.value);
           break;
         }
       }
diff --git a/pkg/test_runner/lib/test_runner.dart b/pkg/test_runner/lib/test_runner.dart
index 59fcb9f..617b454 100644
--- a/pkg/test_runner/lib/test_runner.dart
+++ b/pkg/test_runner/lib/test_runner.dart
@@ -88,12 +88,11 @@
 
 /// Finds the named configuration to test according to the test matrix
 /// information and the command line options.
-Map<String, Set<Builder>> resolveNamedConfigurations(
+Map<String, Set<Builder>>? resolveNamedConfigurations(
     TestMatrix testMatrix,
     String requestedBranch,
     List<String> requestedNamedConfigurations,
-    String requestedBuilder) {
-  assert(requestedBranch != null);
+    String? requestedBuilder) {
   var testedConfigurations = <String, Set<Builder>>{};
   var foundBuilder = false;
   for (var builder in testMatrix.builders) {
@@ -159,7 +158,7 @@
 }
 
 /// Locates the merge base between head and the [branch] on the given [remote].
-Future<String> findMergeBase(String remote, String branch) async {
+Future<String> findMergeBase(String? remote, String? branch) async {
   var arguments = ["merge-base", "$remote/$branch", "HEAD"];
   var result =
       await Process.run("git", arguments, runInShell: Platform.isWindows);
@@ -223,7 +222,7 @@
   client.close();
   // Remove XSSI protection prefix )]}'\n before parsing the response.
   var object = jsonDecode(responseString.substring(5)) as Map<String, dynamic>;
-  var builds = object["builds"] as List<dynamic>;
+  var builds = object["builds"] as List<dynamic>?;
   if (builds == null || builds.isEmpty) {
     throw NoResultsForCommitException(
         "Builder $builder hasn't built commit $commit");
@@ -235,8 +234,8 @@
   }
   var resultsPath = buildFileCloudPath(builder, "$buildNumber", "results.json");
   var flakyPath = buildFileCloudPath(builder, "$buildNumber", "flaky.json");
-  if (await lsGsutil(resultsPath) == null ||
-      await lsGsutil(flakyPath) == null) {
+  if ((await lsGsutil(resultsPath)).isEmpty ||
+      (await lsGsutil(flakyPath)).isEmpty) {
     throw NoResultsForCommitException(
         "Build $buildNumber did not upload results");
   }
@@ -279,7 +278,7 @@
 }
 
 void overrideConfiguration(Map<String, Map<String, dynamic>> results,
-    String configuration, String newConfiguration) {
+    String configuration, String? newConfiguration) {
   results.forEach((String key, Map<String, dynamic> result) {
     if (result["configuration"] == configuration) {
       result["configuration"] = newConfiguration;
@@ -287,7 +286,7 @@
   });
 }
 
-void printUsage(ArgParser parser, {String error, bool printOptions = false}) {
+void printUsage(ArgParser parser, {String? error, bool printOptions = false}) {
   if (error != null) {
     print("$error\n");
     exitCode = 1;
@@ -365,10 +364,10 @@
     return;
   }
 
-  var requestedBuilder = options["builder"] as String;
+  var requestedBuilder = options["builder"] as String?;
   var requestedNamedConfigurations =
       (options["named-configuration"] as List).cast<String>();
-  var localConfiguration = options["local-configuration"] as String;
+  var localConfiguration = options["local-configuration"] as String?;
 
   if (requestedBuilder == null && requestedNamedConfigurations.isEmpty) {
     printUsage(parser,
@@ -410,7 +409,7 @@
 
   // Print information about the resolved builders to compare with.
   for (var namedConfiguration in namedConfigurations) {
-    var testedBuilders = testedConfigurations[namedConfiguration];
+    var testedBuilders = testedConfigurations[namedConfiguration]!;
     var onWhichBuilders = testedBuilders.length == 1
         ? "builder ${testedBuilders.single.name}"
         : "builders${testedBuilders.map((b) => "\n  ${b.name}").join()}";
@@ -425,9 +424,9 @@
   }
 
   // Use given commit or find out where the current HEAD branched.
-  var commit = options["commit"] as String ??
+  var commit = options["commit"] as String? ??
       await findMergeBase(
-          options["remote"] as String, options["branch"] as String);
+          options["remote"] as String?, options["branch"] as String?);
   print("Base commit is $commit");
 
   // Store the downloaded results and our test results in a temporary directory.
diff --git a/pkg/test_runner/pubspec.yaml b/pkg/test_runner/pubspec.yaml
index 26f868f..119ef05 100644
--- a/pkg/test_runner/pubspec.yaml
+++ b/pkg/test_runner/pubspec.yaml
@@ -7,11 +7,12 @@
 publish_to: none
 
 environment:
-  sdk: "^2.9.0"
+  sdk: '>=2.12.0 <3.0.0'
 
 # Use 'any' constraints here; we get our versions from the DEPS file.
 dependencies:
   args: any
+  collection: any
   dart2js_tools: any
   package_config: any
   path: any
diff --git a/pkg/test_runner/test/browser_controller_test.dart b/pkg/test_runner/test/browser_controller_test.dart
index b9738e0..493956c 100644
--- a/pkg/test_runner/test/browser_controller_test.dart
+++ b/pkg/test_runner/test/browser_controller_test.dart
@@ -10,13 +10,15 @@
 import 'package:test_runner/src/service/web_driver_service.dart';
 
 void main() async {
-  if (Platform.environment.containsKey('CHROME_PATH')) {
+  final chromePath = Platform.environment['CHROME_PATH'];
+  if (chromePath != null) {
     print('Testing Chrome');
-    await testChrome();
+    await testChrome(chromePath);
   }
-  if (Platform.environment.containsKey('FIREFOX_PATH')) {
+  final firefoxPath = Platform.environment['FIREFOX_PATH'];
+  if (firefoxPath != null) {
     print('Testing Firefox');
-    await testFirefox();
+    await testFirefox(firefoxPath);
   }
   if (Platform.isMacOS) {
     print('Testing Safari');
@@ -24,17 +26,16 @@
   }
 }
 
-Future<void> testChrome() {
-  return testBrowser(Chrome(Platform.environment['CHROME_PATH']));
+Future<void> testChrome(String path) {
+  return testBrowser(Chrome(path));
 }
 
-Future<void> testFirefox() {
-  return testBrowser(Firefox(Platform.environment['FIREFOX_PATH']));
+Future<void> testFirefox(String path) {
+  return testBrowser(Firefox(path));
 }
 
 Future<void> testSafari() async {
-  var service = WebDriverService.fromRuntime(Runtime.safari);
-  await service.start();
+  var service = await WebDriverService.startServiceForRuntime(Runtime.safari);
   await testBrowser(Safari(service.port));
   service.allDone();
 }
diff --git a/pkg/test_runner/test/browser_test_runner_test.dart b/pkg/test_runner/test/browser_test_runner_test.dart
index e9bf1a6..39809c9 100644
--- a/pkg/test_runner/test/browser_test_runner_test.dart
+++ b/pkg/test_runner/test/browser_test_runner_test.dart
@@ -16,6 +16,9 @@
     testDriverErrorPort: 0,
     testServerPort: 0,
     testServerCrossOriginPort: 0,
+    outputDirectory: '',
+    reproducingArguments: [],
+    sharedOptions: [],
   );
   await configuration.startServers();
   try {
diff --git a/pkg/test_runner/test/compare_results/compare_results_test.dart b/pkg/test_runner/test/compare_results/compare_results_test.dart
index 414ac6f..2a8b174 100644
--- a/pkg/test_runner/test/compare_results/compare_results_test.dart
+++ b/pkg/test_runner/test/compare_results/compare_results_test.dart
@@ -4,8 +4,6 @@
 
 // Test that compare results works as expected.
 
-// @dart = 2.9
-
 import 'package:expect/expect.dart';
 import 'package:test_runner/bot_results.dart';
 import '../../bin/compare_results.dart';
@@ -141,17 +139,17 @@
 }
 
 void _expectEvent(Event actual,
-    {bool isNew,
-    bool isNewPassing,
-    bool isNewFailing,
-    bool changed,
-    bool unchanged,
-    bool remainedPassing,
-    bool remainedFailing,
-    bool flaked,
-    bool fixed,
-    bool broke,
-    String description}) {
+    {bool? isNew,
+    bool? isNewPassing,
+    bool? isNewFailing,
+    bool? changed,
+    bool? unchanged,
+    bool? remainedPassing,
+    bool? remainedFailing,
+    bool? flaked,
+    bool? fixed,
+    bool? broke,
+    String? description}) {
   if (isNew != null) {
     Expect.equals(isNew, actual.isNew, 'isNew mismatch');
   }
diff --git a/pkg/test_runner/test/skipping_dart2js_compilations_test.dart b/pkg/test_runner/test/skipping_dart2js_compilations_test.dart
index 7372f6c..969a1bb 100644
--- a/pkg/test_runner/test/skipping_dart2js_compilations_test.dart
+++ b/pkg/test_runner/test/skipping_dart2js_compilations_test.dart
@@ -27,46 +27,48 @@
 import 'package:test_runner/src/repository.dart';
 import 'package:test_runner/src/test_case.dart';
 
+import 'utils.dart';
+
 /// This class is reponsible for setting up the files necessary for this test
 /// as well as touching a file.
 class FileUtils {
-  Directory tempDir;
-  File testJs;
-  File testJsDeps;
-  File testDart;
-  File testSnapshot;
+  late Directory tempDir;
+  File? testJs;
+  File? testJsDeps;
+  File? testDart;
+  File? testSnapshot;
 
   FileUtils(
-      {bool createJs,
-      bool createJsDeps,
-      bool createDart,
-      bool createSnapshot}) {
+      {required bool createJs,
+      required bool createJsDeps,
+      required bool createDart,
+      required bool createSnapshot}) {
     tempDir = Directory.systemTemp
         .createTempSync('dart_skipping_dart2js_compilations');
     if (createJs) {
       testJs = _createFile(testJsFilePath);
-      _writeToFile(testJs, "test.js content");
+      _writeToFile(testJs!, "test.js content");
     }
     if (createSnapshot) {
       testSnapshot = _createFile(testSnapshotFilePath);
-      _writeToFile(testSnapshot, "dart2js snapshot");
+      _writeToFile(testSnapshot!, "dart2js snapshot");
     }
     if (createDart) {
       testDart = _createFile(testDartFilePath);
-      _writeToFile(testDart, "dart code");
+      _writeToFile(testDart!, "dart code");
     }
     if (createJsDeps) {
       testJsDeps = _createFile(testJsDepsFilePath);
       var path = Path(tempDir.path).append("test.dart").absolute;
-      _writeToFile(testJsDeps, "file://$path");
+      _writeToFile(testJsDeps!, "file://$path");
     }
   }
 
   void cleanup() {
-    if (testJs != null) testJs.deleteSync();
-    if (testJsDeps != null) testJsDeps.deleteSync();
-    if (testDart != null) testDart.deleteSync();
-    if (testSnapshot != null) testSnapshot.deleteSync();
+    if (testJs != null) testJs!.deleteSync();
+    if (testJsDeps != null) testJsDeps!.deleteSync();
+    if (testDart != null) testDart!.deleteSync();
+    if (testSnapshot != null) testSnapshot!.deleteSync();
 
     // if the script did run, it created this file, so we need to delete it
     var file = File(scriptOutputPath.toNativePath());
@@ -102,12 +104,9 @@
   }
 
   void _writeToFile(File file, String content) {
-    if (content != null) {
-      var fd =
-          File(file.resolveSymbolicLinksSync()).openSync(mode: FileMode.write);
-      fd.writeStringSync(content);
-      fd.closeSync();
-    }
+    File(file.resolveSymbolicLinksSync()).openSync(mode: FileMode.write)
+      ..writeStringSync(content)
+      ..closeSync();
   }
 
   String _readFile(File file) {
@@ -153,7 +152,7 @@
   var bootstrapDeps = [Uri.parse("file://${fileUtils.testSnapshotFilePath}")];
   return CompilationCommand('dart2js', fileUtils.testJsFilePath.toNativePath(),
       bootstrapDeps, executable, arguments, {},
-      alwaysCompile: false);
+      alwaysCompile: false, workingDirectory: Directory.current.path);
 }
 
 void main() {
@@ -205,43 +204,37 @@
     fs_upToDate.cleanup();
   }
 
-  void touchFilesAndRunTests() {
-    fs_notUpToDate_snapshot.touchFile(fs_notUpToDate_snapshot.testSnapshot);
-    fs_notUpToDate_dart.touchFile(fs_notUpToDate_dart.testDart);
-    fs_upToDate.touchFile(fs_upToDate.testJs);
+  Future<void> touchFilesAndRunTests() async {
+    fs_notUpToDate_snapshot.touchFile(fs_notUpToDate_snapshot.testSnapshot!);
+    fs_notUpToDate_dart.touchFile(fs_notUpToDate_dart.testDart!);
+    fs_upToDate.touchFile(fs_upToDate.testJs!);
 
     Future runTest(String name, FileUtils fileUtils, bool shouldRun) {
       var completedHandler = CommandCompletedHandler(fileUtils, shouldRun);
       var command = makeCompilationCommand(name, fileUtils) as ProcessCommand;
-      var process = RunningProcess(command, 60);
+      var process = RunningProcess(command, 60,
+          configuration: makeConfiguration([], 'dummy'));
       return process.run().then((CommandOutput output) {
         completedHandler.processCompletedTest(output);
       });
     }
 
-    // We run the tests in sequence, so that if one of them fails we clean up
-    // everything and throw.
-    runTest("fs_noTestJs", fs_noTestJs, true).then((_) {
-      return runTest("fs_noTestJsDeps", fs_noTestJsDeps, true);
-    }).then((_) {
-      return runTest("fs_noTestDart", fs_noTestDart, true);
-    }).then((_) {
-      return runTest("fs_noTestSnapshot", fs_noTestSnapshot, true);
-    }).then((_) {
-      return runTest("fs_notUpToDate_snapshot", fs_notUpToDate_snapshot, true);
-    }).then((_) {
-      return runTest("fs_notUpToDate_dart", fs_notUpToDate_dart, true);
-    }).then((_) {
+    try {
+      // We run the tests in sequence, so that if one of them fails we clean up
+      // everything and throw.
+      await runTest("fs_noTestJs", fs_noTestJs, true);
+      await runTest("fs_noTestJsDeps", fs_noTestJsDeps, true);
+      await runTest("fs_noTestDart", fs_noTestDart, true);
+      await runTest("fs_noTestSnapshot", fs_noTestSnapshot, true);
+      await runTest("fs_notUpToDate_snapshot", fs_notUpToDate_snapshot, true);
+      await runTest("fs_notUpToDate_dart", fs_notUpToDate_dart, true);
       // This is the only test where all dependencies are present and the
       // test.js file is newer than all the others. So we pass 'false' for
       // shouldRun.
-      return runTest("fs_upToDate", fs_upToDate, false);
-    }).catchError((error) {
+      await runTest("fs_upToDate", fs_upToDate, false);
+    } finally {
       cleanup();
-      throw error;
-    }).then((_) {
-      cleanup();
-    });
+    }
   }
 
   // We need to wait some time to make sure that the files we 'touch' get a
diff --git a/pkg/test_runner/test/static_error_test.dart b/pkg/test_runner/test/static_error_test.dart
index 7442db8..b50a471 100644
--- a/pkg/test_runner/test/static_error_test.dart
+++ b/pkg/test_runner/test/static_error_test.dart
@@ -387,7 +387,12 @@
 }
 
 void expectValidate(List<StaticError> expected, List<StaticError> actual,
-    String expectedValidation) {
+    String? expectedValidation) {
   var actualValidation = StaticError.validateExpectations(expected, actual);
-  Expect.stringEquals(expectedValidation, actualValidation);
+  if (expectedValidation == null) {
+    Expect.isNull(actualValidation);
+  } else {
+    Expect.isNotNull(actualValidation);
+    Expect.stringEquals(expectedValidation, actualValidation!);
+  }
 }
diff --git a/pkg/test_runner/test/test_file_test.dart b/pkg/test_runner/test/test_file_test.dart
index 9b1f445..06957f6 100644
--- a/pkg/test_runner/test/test_file_test.dart
+++ b/pkg/test_runner/test/test_file_test.dart
@@ -49,7 +49,7 @@
   Expect.listEquals(<String>[], file.otherResources);
   Expect.listEquals(<String>[], file.sharedObjects);
 
-  Expect.isNull(file.environment);
+  Expect.isEmpty(file.environment.entries);
   Expect.isNull(file.packages);
 
   Expect.isFalse(file.isMultitest);
@@ -159,7 +159,7 @@
 void testParseEnvironment() {
   // No environment.
   var file = parseTestFile("");
-  Expect.isNull(file.environment);
+  Expect.isTrue(file.environment.isEmpty);
 
   // Without values.
   file = parseTestFile("""
@@ -188,7 +188,7 @@
   /\/ Packages=packages thing
   """);
   Expect.isTrue(
-      file.packages.endsWith("${Platform.pathSeparator}packages thing"));
+      file.packages!.endsWith("${Platform.pathSeparator}packages thing"));
 
   // "none" is left alone.
   file = parseTestFile("""
@@ -809,11 +809,19 @@
   // don't want to depend on the hash algorithm, so we can't really be more
   // specific than that.
   var testFile = parseTestFile("", path: "a_test.dart");
-  Expect.isTrue(testFile.shardHash is int);
+  Expect.type<int>(testFile.shardHash);
 
   // VM test files are hard-coded to return hash zero because they don't have a
   // path to base the hash on.
-  Expect.equals(0, TestFile.vmUnitTest().shardHash);
+  Expect.equals(
+      0,
+      TestFile.vmUnitTest(
+              hasCompileError: false,
+              hasCrash: false,
+              hasRuntimeError: false,
+              hasStaticWarning: false,
+              hasSyntaxError: false)
+          .shardHash);
 }
 
 void expectParseErrorExpectations(String source, List<StaticError> errors) {
diff --git a/pkg/test_runner/test/test_runner_test.dart b/pkg/test_runner/test/test_runner_test.dart
index 2fd217a..d1f7034 100644
--- a/pkg/test_runner/test/test_runner_test.dart
+++ b/pkg/test_runner/test/test_runner_test.dart
@@ -13,9 +13,11 @@
 import "package:test_runner/src/command.dart";
 import "package:test_runner/src/configuration.dart";
 import "package:test_runner/src/options.dart";
+import 'package:test_runner/src/path.dart';
 import "package:test_runner/src/process_queue.dart";
 import "package:test_runner/src/repository.dart";
 import "package:test_runner/src/test_case.dart";
+import 'package:test_runner/src/test_file.dart';
 import "package:test_runner/src/test_progress.dart" as progress;
 import "package:test_runner/src/test_suite.dart";
 
@@ -113,7 +115,11 @@
       Iterable<Expectation> expectations) {
     var configuration = OptionsParser().parse(['--timeout', '$timeout'])[0];
     return TestCase(
-        name, [command], configuration, Set<Expectation>.from(expectations));
+        name,
+        [command],
+        configuration,
+        Set<Expectation>.from(expectations),
+        TestFile.parse(Path('suite'), '/dummy_test.dart', ''));
   }
 }
 
@@ -146,7 +152,6 @@
       case 'fail-unexpected':
       case 'fail':
         throw "This test always fails, to test the test scripts.";
-        break;
       case 'timeout':
         // This process should be killed by the test after DEFAULT_TIMEOUT
         Timer(const Duration(hours: 42), () {});
diff --git a/pkg/test_runner/test/update_errors_test.dart b/pkg/test_runner/test/update_errors_test.dart
index 365ed14..612e69f 100644
--- a/pkg/test_runner/test/update_errors_test.dart
+++ b/pkg/test_runner/test/update_errors_test.dart
@@ -645,10 +645,10 @@
 }
 
 void expectUpdate(String original,
-    {List<StaticError> errors,
-    Set<ErrorSource> remove,
-    bool includeContext,
-    String expected}) {
+    {List<StaticError>? errors,
+    Set<ErrorSource>? remove,
+    bool? includeContext,
+    String? expected}) {
   errors ??= const [];
   remove ??= ErrorSource.all.toSet();
   includeContext ??= false;
@@ -659,7 +659,7 @@
     // Not using Expect.equals() because the diffs it shows aren't helpful for
     // strings this large.
     var actualLines = actual.split("\n");
-    var expectedLines = expected.split("\n");
+    var expectedLines = expected!.split("\n");
 
     // Figure out which leading lines do match so we can ignore those and
     // highlight the offending ones.
diff --git a/pkg/test_runner/test/utils.dart b/pkg/test_runner/test/utils.dart
index f5e14cb..2a59f59 100644
--- a/pkg/test_runner/test/utils.dart
+++ b/pkg/test_runner/test/utils.dart
@@ -34,13 +34,13 @@
     {int line = 1,
     int column = 2,
     int length = 0,
-    String analyzerError,
-    String cfeError,
-    String webError,
-    String contextError,
-    List<StaticError> context}) {
+    String? analyzerError,
+    String? cfeError,
+    String? webError,
+    String? contextError,
+    List<StaticError>? context}) {
   ErrorSource source;
-  String message;
+  String? message;
   if (analyzerError != null) {
     assert(cfeError == null);
     assert(webError == null);
@@ -63,7 +63,7 @@
   }
 
   var error =
-      StaticError(source, message, line: line, column: column, length: length);
+      StaticError(source, message!, line: line, column: column, length: length);
   if (context != null) error.contextMessages.addAll(context);
   return error;
 }
diff --git a/pkg/test_runner/tool/convert_multitest.dart b/pkg/test_runner/tool/convert_multitest.dart
index 0bc1a3a..59c459a 100644
--- a/pkg/test_runner/tool/convert_multitest.dart
+++ b/pkg/test_runner/tool/convert_multitest.dart
@@ -22,14 +22,8 @@
 
 Future<List<StaticError>> getErrors(
     List<String> options, String filePath) async {
-  var analyzerErrors = await runAnalyzer(filePath, options);
-  if (analyzerErrors == null) {
-    exit(1);
-  }
-  var cfeErrors = await runCfe(filePath, options);
-  if (cfeErrors == null) {
-    exit(1);
-  }
+  var analyzerErrors = await runAnalyzer(File(filePath), options);
+  var cfeErrors = await runCfe(File(filePath), options);
   return [...analyzerErrors, ...cfeErrors];
 }
 
@@ -87,7 +81,7 @@
       throw "internal error: cannot process line '$line'";
     } else if (matches.length == 1) {
       var match = matches.single;
-      var annotation = Annotation.tryParse(line);
+      var annotation = Annotation.tryParse(line)!;
       if (annotation.outcomes.length != 1) {
         throw UnableToConvertException("annotation has multiple outcomes");
       }
@@ -248,7 +242,7 @@
   parser.addFlag("verbose", abbr: "v", help: "print additional information");
   parser.addFlag("write", abbr: "w", help: "write output to input file");
   parser.addMultiOption("enable-experiment",
-      help: "Enable one or more experimental features");
+      defaultsTo: <String>[], help: "Enable one or more experimental features");
 
   var results = parser.parse(arguments);
   if (results.rest.isEmpty) {
diff --git a/pkg/test_runner/tool/orphan_files.dart b/pkg/test_runner/tool/orphan_files.dart
index 6457209..d5785de 100644
--- a/pkg/test_runner/tool/orphan_files.dart
+++ b/pkg/test_runner/tool/orphan_files.dart
@@ -31,7 +31,7 @@
   }
 }
 
-AnalysisContext _analysisContext;
+late AnalysisContext _analysisContext;
 
 void _checkTestDirectory(Directory directory) {
   print('-- ${directory.path} --');
@@ -86,7 +86,7 @@
 
   for (var directive in unit.directives) {
     if (directive is UriBasedDirective) {
-      add(directive.uri.stringValue);
+      add(directive.uri.stringValue!);
     }
   }
 }
diff --git a/pkg/test_runner/tool/update_static_error_tests.dart b/pkg/test_runner/tool/update_static_error_tests.dart
index 7ebda75..a66e98c 100644
--- a/pkg/test_runner/tool/update_static_error_tests.dart
+++ b/pkg/test_runner/tool/update_static_error_tests.dart
@@ -80,16 +80,16 @@
   var insertSources = <ErrorSource>{};
 
   for (var source in results["remove"] as List<String>) {
-    removeSources.add(ErrorSource.find(source));
+    removeSources.add(ErrorSource.find(source)!);
   }
 
   for (var source in results["insert"] as List<String>) {
-    insertSources.add(ErrorSource.find(source));
+    insertSources.add(ErrorSource.find(source)!);
   }
 
   for (var source in results["update"] as List<String>) {
-    removeSources.add(ErrorSource.find(source));
-    insertSources.add(ErrorSource.find(source));
+    removeSources.add(ErrorSource.find(source)!);
+    insertSources.add(ErrorSource.find(source)!);
   }
 
   if (results["remove-all"] as bool) {
@@ -145,10 +145,10 @@
 }
 
 Future<void> _processFile(File file,
-    {bool dryRun,
-    bool includeContext,
-    Set<ErrorSource> remove,
-    Set<ErrorSource> insert}) async {
+    {required bool dryRun,
+    required bool includeContext,
+    required Set<ErrorSource> remove,
+    required Set<ErrorSource> insert}) async {
   stdout.write("${file.path}...");
   var source = file.readAsStringSync();
   var testFile = TestFile.parse(Path("."), file.absolute.path, source);
@@ -165,17 +165,12 @@
   var errors = <StaticError>[];
   if (insert.contains(ErrorSource.analyzer)) {
     stdout.write("\r${file.path} (Running analyzer...)");
-    var fileErrors = await runAnalyzer(file.absolute.path, options);
-    if (fileErrors == null) {
-      print("Error: failed to update ${file.path}");
-    } else {
-      errors.addAll(fileErrors);
-    }
+    errors.addAll(await runAnalyzer(file, options));
   }
 
   // If we're inserting web errors, we also need to gather the CFE errors to
   // tell which web errors are web-specific.
-  List<StaticError> cfeErrors;
+  final cfeErrors = <StaticError>[];
   if (insert.contains(ErrorSource.cfe) || insert.contains(ErrorSource.web)) {
     var cfeOptions = [
       if (testFile.requirements.contains(Feature.nnbdWeak)) "--nnbd-weak",
@@ -185,10 +180,8 @@
     // Clear the previous line.
     stdout.write("\r${file.path}                      ");
     stdout.write("\r${file.path} (Running CFE...)");
-    cfeErrors = await runCfe(file.absolute.path, cfeOptions);
-    if (cfeErrors == null) {
-      print("Error: failed to update ${file.path}");
-    } else if (insert.contains(ErrorSource.cfe)) {
+    cfeErrors.addAll(await runCfe(file, cfeOptions));
+    if (insert.contains(ErrorSource.cfe)) {
       errors.addAll(cfeErrors);
     }
   }
@@ -197,12 +190,7 @@
     // Clear the previous line.
     stdout.write("\r${file.path}                      ");
     stdout.write("\r${file.path} (Running dart2js...)");
-    var fileErrors = await runDart2js(file.absolute.path, options, cfeErrors);
-    if (fileErrors == null) {
-      print("Error: failed to update ${file.path}");
-    } else {
-      errors.addAll(fileErrors);
-    }
+    errors.addAll(await runDart2js(file, options, cfeErrors));
   }
 
   var result = updateErrorExpectations(source, errors,
@@ -217,15 +205,15 @@
   }
 }
 
-/// Invoke analyzer on [path] and gather all static errors it reports.
-Future<List<StaticError>> runAnalyzer(String path, List<String> options) async {
+/// Invoke analyzer on [file] and gather all static errors it reports.
+Future<List<StaticError>> runAnalyzer(File file, List<String> options) async {
   // TODO(rnystrom): Running the analyzer command line each time is very slow.
   // Either import the analyzer as a library, or at least invoke it in a batch
   // mode.
   var result = await Process.run(_analyzerPath, [
     ...options,
     "--format=json",
-    path,
+    file.absolute.path,
   ]);
 
   // Analyzer returns 3 when it detects errors, 2 when it detects
@@ -233,7 +221,8 @@
   // hints and --fatal-hints or --fatal-infos are enabled.
   if (result.exitCode < 0 || result.exitCode > 3) {
     print("Analyzer run failed: ${result.stdout}\n${result.stderr}");
-    return null;
+    print("Error: failed to update ${file.path}");
+    return const [];
   }
 
   var errors = <StaticError>[];
@@ -242,8 +231,8 @@
   return [...errors, ...warnings];
 }
 
-/// Invoke CFE on [path] and gather all static errors it reports.
-Future<List<StaticError>> runCfe(String path, List<String> options) async {
+/// Invoke CFE on [file] and gather all static errors it reports.
+Future<List<StaticError>> runCfe(File file, List<String> options) async {
   // TODO(rnystrom): Running the CFE command line each time is slow and wastes
   // time generating code, which we don't care about. Import it as a library or
   // at least run it in batch mode.
@@ -253,18 +242,19 @@
     "--verify",
     "-o",
     "dev:null", // Output is only created for file URIs.
-    path,
+    file.absolute.path,
   ]);
 
   // Running the above command may generate a dill file next to the test, which
   // we don't want, so delete it if present.
-  var file = File("$path.dill");
-  if (await file.exists()) {
-    await file.delete();
+  var dill = File("${file.absolute.path}.dill");
+  if (await dill.exists()) {
+    await dill.delete();
   }
   if (result.exitCode != 0) {
     print("CFE run failed: ${result.stdout}\n${result.stderr}");
-    return null;
+    print("Error: failed to update ${file.path}");
+    return const [];
   }
   var errors = <StaticError>[];
   var warnings = <StaticError>[];
@@ -272,14 +262,14 @@
   return [...errors, ...warnings];
 }
 
-/// Invoke dart2js on [path] and gather all static errors it reports.
+/// Invoke dart2js on [file] and gather all static errors it reports.
 Future<List<StaticError>> runDart2js(
-    String path, List<String> options, List<StaticError> cfeErrors) async {
+    File file, List<String> options, List<StaticError> cfeErrors) async {
   var result = await Process.run(_dart2jsPath, [
     ...options,
     "-o",
     "dev:null", // Output is only created for file URIs.
-    path,
+    file.absolute.path,
   ]);
 
   var errors = <StaticError>[];
@@ -303,8 +293,8 @@
 String _findBinary(String name, String windowsExtension) {
   var binary = Platform.isWindows ? "$name.$windowsExtension" : name;
 
-  String newestPath;
-  DateTime newestTime;
+  String? newestPath;
+  DateTime? newestTime;
 
   var buildDirectory = Directory(Platform.isMacOS ? "xcodebuild" : "out");
   if (buildDirectory.existsSync()) {
diff --git a/pkg/vm_service/test/get_stack_test.dart b/pkg/vm_service/test/get_stack_test.dart
index 138876b..d1b42d3 100644
--- a/pkg/vm_service/test/get_stack_test.dart
+++ b/pkg/vm_service/test/get_stack_test.dart
@@ -95,7 +95,7 @@
   (VmService service, IsolateRef isolateRef) async {
     final result = await service.getStack(isolateRef.id!);
 
-    expect(result.frames, hasLength(10));
+    expect(result.frames, hasLength(6));
     expect(result.asyncCausalFrames, hasLength(26));
     expect(result.awaiterFrames, hasLength(13));
 
@@ -105,10 +105,6 @@
       [equals('Regular'), anything], // Internal mech. ..
       [equals('Regular'), anything],
       [equals('Regular'), anything],
-      [equals('Regular'), anything],
-      [equals('Regular'), anything],
-      [equals('Regular'), anything],
-      [equals('Regular'), anything],
       [equals('Regular'), endsWith(' _RawReceivePortImpl._handleMessage')],
     ]);
 
diff --git a/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart b/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
index 35a6493..f8decf0 100644
--- a/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
@@ -51,7 +51,7 @@
     var frames = stack['frames'];
     var asyncFrames = stack['asyncCausalFrames'];
     var awaiterFrames = stack['awaiterFrames'];
-    expect(frames.length, greaterThanOrEqualTo(20));
+    expect(frames.length, greaterThanOrEqualTo(12));
     expect(asyncFrames.length, greaterThan(frames.length));
     expect(awaiterFrames.length, greaterThan(frames.length));
     expect(stack['truncated'], false);
diff --git a/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
index e346afa..8570a28 100644
--- a/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
@@ -51,7 +51,7 @@
     var frames = stack['frames'];
     var asyncFrames = stack['asyncCausalFrames'];
     var awaiterFrames = stack['awaiterFrames'];
-    expect(frames.length, greaterThanOrEqualTo(20));
+    expect(frames.length, greaterThanOrEqualTo(12));
     expect(asyncFrames.length, greaterThan(frames.length));
     expect(awaiterFrames.length, greaterThan(frames.length));
     expect(stack['truncated'], false);
diff --git a/runtime/tests/vm/dart/await_in_custom_zone_test.dart b/runtime/tests/vm/dart/await_in_custom_zone_test.dart
new file mode 100644
index 0000000..70dbfdd
--- /dev/null
+++ b/runtime/tests/vm/dart/await_in_custom_zone_test.dart
@@ -0,0 +1,197 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that 'await' implementation calls Zone callbacks from
+// correct Zones.
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+List<String> log = [];
+
+class TestZone {
+  final String name;
+  TestZone(this.name);
+
+  static T run<T>(String name, T Function() callback) {
+    final tz = TestZone(name);
+    final zone = Zone.current.fork(
+        specification: ZoneSpecification(
+            runUnary: tz.runUnary,
+            runBinary: tz.runBinary,
+            registerUnaryCallback: tz.registerUnaryCallback,
+            registerBinaryCallback: tz.registerBinaryCallback,
+            scheduleMicrotask: tz.scheduleMicrotask));
+    return zone.run(callback);
+  }
+
+  R runUnary<R, T>(
+      Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f, T arg) {
+    log.add('$name.runUnary');
+    return parent.runUnary(zone, f, arg);
+  }
+
+  R runBinary<R, T1, T2>(Zone self, ZoneDelegate parent, Zone zone,
+      R Function(T1 arg1, T2 arg2) f, T1 arg1, T2 arg2) {
+    log.add('$name.runBinary');
+    return parent.runBinary(zone, f, arg1, arg2);
+  }
+
+  ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(
+      Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f) {
+    log.add('$name.registerUnaryCallback');
+    return parent.registerUnaryCallback(zone, (T arg) {
+      log.add('$name.unaryCallback');
+      return f(arg);
+    });
+  }
+
+  ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(Zone self,
+      ZoneDelegate parent, Zone zone, R Function(T1 arg1, T2 arg2) f) {
+    log.add('$name.registerBinaryCallback');
+    return parent.registerBinaryCallback(zone, (T1 arg1, T2 arg2) {
+      log.add('$name.binaryCallback');
+      return f(arg1, arg2);
+    });
+  }
+
+  void scheduleMicrotask(Zone self, ZoneDelegate parent, Zone zone, void f()) {
+    log.add('$name.scheduleMicrotask');
+    parent.scheduleMicrotask(zone, f);
+  }
+}
+
+Future<void> foo() async {
+  log.add('--- step 3');
+}
+
+Future<void> baz() async {
+  log.add('--- step 8');
+}
+
+Future<void> bar() async {
+  log.add('--- step 6');
+
+  Future f = TestZone.run('Z3', () {
+    log.add('--- step 7');
+    return baz();
+  });
+
+  log.add('--- step 9');
+  await TestZone.run('Z4', () async {
+    log.add('--- step 10');
+    await f;
+    log.add('--- step 13');
+  });
+  log.add('--- step 14');
+}
+
+main() async {
+  log.add('--- start');
+  await TestZone.run('Z1', () async {
+    log.add('--- step 1');
+    await null;
+    log.add('--- step 2');
+    await foo();
+
+    log.add('--- step 4');
+    await TestZone.run('Z2', () async {
+      log.add('--- step 5');
+      Future f = bar();
+
+      log.add('--- step 11');
+      await TestZone.run('Z4', () async {
+        log.add('--- step 12');
+        await f;
+        log.add('--- step 15');
+      });
+      log.add('--- step 16');
+    });
+    log.add('--- step 17');
+  });
+  log.add('--- end');
+
+  print('Actual log = [');
+  for (int i = 0; i < log.length; ++i) {
+    print("  /* $i */ '${log[i]}',");
+  }
+  print('];');
+
+  List<String> expectedLog = [
+    /* 0 */ '--- start',
+    /* 1 */ '--- step 1',
+    /* 2 */ 'Z1.registerUnaryCallback',
+    /* 3 */ 'Z1.registerBinaryCallback',
+    /* 4 */ 'Z1.scheduleMicrotask',
+    /* 5 */ 'Z1.runUnary',
+    /* 6 */ 'Z1.unaryCallback',
+    /* 7 */ '--- step 2',
+    /* 8 */ '--- step 3',
+    /* 9 */ 'Z1.scheduleMicrotask',
+    /* 10 */ 'Z1.runUnary',
+    /* 11 */ 'Z1.unaryCallback',
+    /* 12 */ '--- step 4',
+    /* 13 */ '--- step 5',
+    /* 14 */ '--- step 6',
+    /* 15 */ '--- step 7',
+    /* 16 */ '--- step 8',
+    /* 17 */ '--- step 9',
+    /* 18 */ '--- step 10',
+    /* 19 */ 'Z4.registerUnaryCallback',
+    /* 20 */ 'Z2.registerUnaryCallback',
+    /* 21 */ 'Z1.registerUnaryCallback',
+    /* 22 */ 'Z4.registerBinaryCallback',
+    /* 23 */ 'Z2.registerBinaryCallback',
+    /* 24 */ 'Z1.registerBinaryCallback',
+    /* 25 */ 'Z3.scheduleMicrotask',
+    /* 26 */ 'Z2.scheduleMicrotask',
+    /* 27 */ 'Z1.scheduleMicrotask',
+    /* 28 */ 'Z2.registerUnaryCallback',
+    /* 29 */ 'Z1.registerUnaryCallback',
+    /* 30 */ 'Z2.registerBinaryCallback',
+    /* 31 */ 'Z1.registerBinaryCallback',
+    /* 32 */ '--- step 11',
+    /* 33 */ '--- step 12',
+    /* 34 */ 'Z4.registerUnaryCallback',
+    /* 35 */ 'Z2.registerUnaryCallback',
+    /* 36 */ 'Z1.registerUnaryCallback',
+    /* 37 */ 'Z4.registerBinaryCallback',
+    /* 38 */ 'Z2.registerBinaryCallback',
+    /* 39 */ 'Z1.registerBinaryCallback',
+    /* 40 */ 'Z2.registerUnaryCallback',
+    /* 41 */ 'Z1.registerUnaryCallback',
+    /* 42 */ 'Z2.registerBinaryCallback',
+    /* 43 */ 'Z1.registerBinaryCallback',
+    /* 44 */ 'Z4.runUnary',
+    /* 45 */ 'Z2.runUnary',
+    /* 46 */ 'Z1.runUnary',
+    /* 47 */ 'Z1.unaryCallback',
+    /* 48 */ 'Z2.unaryCallback',
+    /* 49 */ 'Z4.unaryCallback',
+    /* 50 */ '--- step 13',
+    /* 51 */ 'Z2.runUnary',
+    /* 52 */ 'Z1.runUnary',
+    /* 53 */ 'Z1.unaryCallback',
+    /* 54 */ 'Z2.unaryCallback',
+    /* 55 */ '--- step 14',
+    /* 56 */ 'Z4.runUnary',
+    /* 57 */ 'Z2.runUnary',
+    /* 58 */ 'Z1.runUnary',
+    /* 59 */ 'Z1.unaryCallback',
+    /* 60 */ 'Z2.unaryCallback',
+    /* 61 */ 'Z4.unaryCallback',
+    /* 62 */ '--- step 15',
+    /* 63 */ 'Z2.runUnary',
+    /* 64 */ 'Z1.runUnary',
+    /* 65 */ 'Z1.unaryCallback',
+    /* 66 */ 'Z2.unaryCallback',
+    /* 67 */ '--- step 16',
+    /* 68 */ 'Z1.runUnary',
+    /* 69 */ 'Z1.unaryCallback',
+    /* 70 */ '--- step 17',
+    /* 71 */ '--- end',
+  ];
+  Expect.listEquals(expectedLog, log);
+}
diff --git a/runtime/tests/vm/dart_2/await_in_custom_zone_test.dart b/runtime/tests/vm/dart_2/await_in_custom_zone_test.dart
new file mode 100644
index 0000000..28fb422
--- /dev/null
+++ b/runtime/tests/vm/dart_2/await_in_custom_zone_test.dart
@@ -0,0 +1,199 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+// This test verifies that 'await' implementation calls Zone callbacks from
+// correct Zones.
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+List<String> log = [];
+
+class TestZone {
+  final String name;
+  TestZone(this.name);
+
+  static T run<T>(String name, T Function() callback) {
+    final tz = TestZone(name);
+    final zone = Zone.current.fork(
+        specification: ZoneSpecification(
+            runUnary: tz.runUnary,
+            runBinary: tz.runBinary,
+            registerUnaryCallback: tz.registerUnaryCallback,
+            registerBinaryCallback: tz.registerBinaryCallback,
+            scheduleMicrotask: tz.scheduleMicrotask));
+    return zone.run(callback);
+  }
+
+  R runUnary<R, T>(
+      Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f, T arg) {
+    log.add('$name.runUnary');
+    return parent.runUnary(zone, f, arg);
+  }
+
+  R runBinary<R, T1, T2>(Zone self, ZoneDelegate parent, Zone zone,
+      R Function(T1 arg1, T2 arg2) f, T1 arg1, T2 arg2) {
+    log.add('$name.runBinary');
+    return parent.runBinary(zone, f, arg1, arg2);
+  }
+
+  ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(
+      Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f) {
+    log.add('$name.registerUnaryCallback');
+    return parent.registerUnaryCallback(zone, (T arg) {
+      log.add('$name.unaryCallback');
+      return f(arg);
+    });
+  }
+
+  ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(Zone self,
+      ZoneDelegate parent, Zone zone, R Function(T1 arg1, T2 arg2) f) {
+    log.add('$name.registerBinaryCallback');
+    return parent.registerBinaryCallback(zone, (T1 arg1, T2 arg2) {
+      log.add('$name.binaryCallback');
+      return f(arg1, arg2);
+    });
+  }
+
+  void scheduleMicrotask(Zone self, ZoneDelegate parent, Zone zone, void f()) {
+    log.add('$name.scheduleMicrotask');
+    parent.scheduleMicrotask(zone, f);
+  }
+}
+
+Future<void> foo() async {
+  log.add('--- step 3');
+}
+
+Future<void> baz() async {
+  log.add('--- step 8');
+}
+
+Future<void> bar() async {
+  log.add('--- step 6');
+
+  Future f = TestZone.run('Z3', () {
+    log.add('--- step 7');
+    return baz();
+  });
+
+  log.add('--- step 9');
+  await TestZone.run('Z4', () async {
+    log.add('--- step 10');
+    await f;
+    log.add('--- step 13');
+  });
+  log.add('--- step 14');
+}
+
+main() async {
+  log.add('--- start');
+  await TestZone.run('Z1', () async {
+    log.add('--- step 1');
+    await null;
+    log.add('--- step 2');
+    await foo();
+
+    log.add('--- step 4');
+    await TestZone.run('Z2', () async {
+      log.add('--- step 5');
+      Future f = bar();
+
+      log.add('--- step 11');
+      await TestZone.run('Z4', () async {
+        log.add('--- step 12');
+        await f;
+        log.add('--- step 15');
+      });
+      log.add('--- step 16');
+    });
+    log.add('--- step 17');
+  });
+  log.add('--- end');
+
+  print('Actual log = [');
+  for (int i = 0; i < log.length; ++i) {
+    print("  /* $i */ '${log[i]}',");
+  }
+  print('];');
+
+  List<String> expectedLog = [
+    /* 0 */ '--- start',
+    /* 1 */ '--- step 1',
+    /* 2 */ 'Z1.registerUnaryCallback',
+    /* 3 */ 'Z1.registerBinaryCallback',
+    /* 4 */ 'Z1.scheduleMicrotask',
+    /* 5 */ 'Z1.runUnary',
+    /* 6 */ 'Z1.unaryCallback',
+    /* 7 */ '--- step 2',
+    /* 8 */ '--- step 3',
+    /* 9 */ 'Z1.scheduleMicrotask',
+    /* 10 */ 'Z1.runUnary',
+    /* 11 */ 'Z1.unaryCallback',
+    /* 12 */ '--- step 4',
+    /* 13 */ '--- step 5',
+    /* 14 */ '--- step 6',
+    /* 15 */ '--- step 7',
+    /* 16 */ '--- step 8',
+    /* 17 */ '--- step 9',
+    /* 18 */ '--- step 10',
+    /* 19 */ 'Z4.registerUnaryCallback',
+    /* 20 */ 'Z2.registerUnaryCallback',
+    /* 21 */ 'Z1.registerUnaryCallback',
+    /* 22 */ 'Z4.registerBinaryCallback',
+    /* 23 */ 'Z2.registerBinaryCallback',
+    /* 24 */ 'Z1.registerBinaryCallback',
+    /* 25 */ 'Z3.scheduleMicrotask',
+    /* 26 */ 'Z2.scheduleMicrotask',
+    /* 27 */ 'Z1.scheduleMicrotask',
+    /* 28 */ 'Z2.registerUnaryCallback',
+    /* 29 */ 'Z1.registerUnaryCallback',
+    /* 30 */ 'Z2.registerBinaryCallback',
+    /* 31 */ 'Z1.registerBinaryCallback',
+    /* 32 */ '--- step 11',
+    /* 33 */ '--- step 12',
+    /* 34 */ 'Z4.registerUnaryCallback',
+    /* 35 */ 'Z2.registerUnaryCallback',
+    /* 36 */ 'Z1.registerUnaryCallback',
+    /* 37 */ 'Z4.registerBinaryCallback',
+    /* 38 */ 'Z2.registerBinaryCallback',
+    /* 39 */ 'Z1.registerBinaryCallback',
+    /* 40 */ 'Z2.registerUnaryCallback',
+    /* 41 */ 'Z1.registerUnaryCallback',
+    /* 42 */ 'Z2.registerBinaryCallback',
+    /* 43 */ 'Z1.registerBinaryCallback',
+    /* 44 */ 'Z4.runUnary',
+    /* 45 */ 'Z2.runUnary',
+    /* 46 */ 'Z1.runUnary',
+    /* 47 */ 'Z1.unaryCallback',
+    /* 48 */ 'Z2.unaryCallback',
+    /* 49 */ 'Z4.unaryCallback',
+    /* 50 */ '--- step 13',
+    /* 51 */ 'Z2.runUnary',
+    /* 52 */ 'Z1.runUnary',
+    /* 53 */ 'Z1.unaryCallback',
+    /* 54 */ 'Z2.unaryCallback',
+    /* 55 */ '--- step 14',
+    /* 56 */ 'Z4.runUnary',
+    /* 57 */ 'Z2.runUnary',
+    /* 58 */ 'Z1.runUnary',
+    /* 59 */ 'Z1.unaryCallback',
+    /* 60 */ 'Z2.unaryCallback',
+    /* 61 */ 'Z4.unaryCallback',
+    /* 62 */ '--- step 15',
+    /* 63 */ 'Z2.runUnary',
+    /* 64 */ 'Z1.runUnary',
+    /* 65 */ 'Z1.unaryCallback',
+    /* 66 */ 'Z2.unaryCallback',
+    /* 67 */ '--- step 16',
+    /* 68 */ 'Z1.runUnary',
+    /* 69 */ 'Z1.unaryCallback',
+    /* 70 */ '--- step 17',
+    /* 71 */ '--- end',
+  ];
+  Expect.listEquals(expectedLog, log);
+}
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 98e305e..4f9b035 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -88,15 +88,15 @@
   V(_SuspendState, set:_functionData, SuspendState_setFunctionData,            \
     0x2b6668ab)                                                                \
   V(_SuspendState, get:_thenCallback, SuspendState_getThenCallback,            \
-    0xff1dccec)                                                                \
+    0x2b9efd21)                                                                \
   V(_SuspendState, set:_thenCallback, SuspendState_setThenCallback,            \
-    0x6446bde9)                                                                \
+    0x753cb4de)                                                                \
   V(_SuspendState, get:_errorCallback, SuspendState_getErrorCallback,          \
-    0x8a6eb3cf)                                                                \
+    0xaeca06ef)                                                                \
   V(_SuspendState, set:_errorCallback, SuspendState_setErrorCallback,          \
-    0x4935f88c)                                                                \
+    0xc40903ac)                                                                \
   V(_SuspendState, _createAsyncCallbacks, SuspendState_createAsyncCallbacks,   \
-    0x4add6c13)                                                                \
+    0x68be1bf3)                                                                \
   V(_SuspendState, _createAsyncStarCallback,                                   \
     SuspendState_createAsyncStarCallback, 0xfa7537e4)                          \
   V(_SuspendState, _resume, SuspendState_resume, 0xc738e9d2)                   \
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index f0fe6a8..80e135e 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -211,7 +211,7 @@
   V(NoSuchMethod, "noSuchMethod")                                              \
   V(NoSuchMethodError, "NoSuchMethodError")                                    \
   V(Null, "Null")                                                              \
-  V(NullThrownError, "NullThrownError")                                        \
+  V(NullThrownError, "_NullThrownError")                                       \
   V(Number, "num")                                                             \
   V(Object, "Object")                                                          \
   V(ObjectPool, "ObjectPool")                                                  \
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
index 1eed466..49c92c7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -692,7 +692,7 @@
 abstract class JavaScriptIndexingBehavior<E> extends JSMutableIndexable<E> {}
 
 /// Thrown by type assertions that fail.
-class TypeErrorImpl extends Error implements TypeError, CastError {
+class TypeErrorImpl extends Error implements TypeError {
   final String _message;
 
   TypeErrorImpl(this._message);
diff --git a/sdk/lib/_internal/js_shared/lib/rti.dart b/sdk/lib/_internal/js_shared/lib/rti.dart
index b7c9881..ca9ab8f 100644
--- a/sdk/lib/_internal/js_shared/lib/rti.dart
+++ b/sdk/lib/_internal/js_shared/lib/rti.dart
@@ -1073,7 +1073,7 @@
   String toString() => _message;
 }
 
-class _TypeError extends _Error implements TypeError, CastError {
+class _TypeError extends _Error implements TypeError {
   _TypeError.fromMessage(String message) : super('TypeError: $message');
 
   factory _TypeError.forType(object, String type) {
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 99ebc23..2431b2a 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -345,7 +345,7 @@
     }
 
     @pragma("vm:invisible")
-    errorCallback(exception, stackTrace) {
+    errorCallback(Object exception, StackTrace stackTrace) {
       if (_trace) {
         print('errorCallback (this=$this, '
             'exception=$exception, stackTrace=$stackTrace)');
@@ -372,15 +372,75 @@
     }
   }
 
+  @pragma("vm:invisible")
+  @pragma("vm:prefer-inline")
+  void _awaitCompletedFuture(_Future future) {
+    assert(future._isComplete);
+    final zone = Zone._current;
+    if (future._hasError) {
+      @pragma("vm:invisible")
+      void run() {
+        final AsyncError asyncError =
+            unsafeCast<AsyncError>(future._resultOrListeners);
+        if (!future._zone.inSameErrorZone(zone)) {
+          // Don't cross zone boundaries with errors.
+          future._zone
+              .handleUncaughtError(asyncError.error, asyncError.stackTrace);
+        } else {
+          zone.runBinary(
+              unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback),
+              asyncError.error,
+              asyncError.stackTrace);
+        }
+      }
+
+      future._zone.scheduleMicrotask(run);
+    } else {
+      @pragma("vm:invisible")
+      void run() {
+        zone.runUnary(unsafeCast<dynamic Function(dynamic)>(_thenCallback),
+            future._resultOrListeners);
+      }
+
+      future._zone.scheduleMicrotask(run);
+    }
+  }
+
+  @pragma("vm:invisible")
+  @pragma("vm:prefer-inline")
+  void _awaitNotFuture(Object? object) {
+    final zone = Zone._current;
+    @pragma("vm:invisible")
+    void run() {
+      zone.runUnary(
+          unsafeCast<dynamic Function(dynamic)>(_thenCallback), object);
+    }
+
+    zone.scheduleMicrotask(run);
+  }
+
   @pragma("vm:entry-point", "call")
   @pragma("vm:invisible")
   Object? _await(Object? object) {
-    if (_trace) print('_awaitAsync (object=$object)');
+    if (_trace) print('_await (object=$object)');
     if (_thenCallback == null) {
       _createAsyncCallbacks();
     }
-    _awaitHelper(object, unsafeCast<dynamic Function(dynamic)>(_thenCallback),
-        unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback));
+    if (object is _Future) {
+      if (object._isComplete) {
+        _awaitCompletedFuture(object);
+      } else {
+        object._thenAwait<dynamic>(
+            unsafeCast<dynamic Function(dynamic)>(_thenCallback),
+            unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback));
+      }
+    } else if (object is! Future) {
+      _awaitNotFuture(object);
+    } else {
+      object.then(unsafeCast<dynamic Function(dynamic)>(_thenCallback),
+          onError:
+              unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback));
+    }
     return _functionData;
   }
 
@@ -501,19 +561,19 @@
 
   @pragma("vm:recognized", "other")
   @pragma("vm:prefer-inline")
-  external set _thenCallback(Function? value);
+  external set _thenCallback(void Function(dynamic)? value);
 
   @pragma("vm:recognized", "other")
   @pragma("vm:prefer-inline")
-  external Function? get _thenCallback;
+  external void Function(dynamic)? get _thenCallback;
 
   @pragma("vm:recognized", "other")
   @pragma("vm:prefer-inline")
-  external set _errorCallback(Function value);
+  external set _errorCallback(dynamic Function(Object, StackTrace)? value);
 
   @pragma("vm:recognized", "other")
   @pragma("vm:prefer-inline")
-  external Function get _errorCallback;
+  external dynamic Function(Object, StackTrace)? get _errorCallback;
 
   @pragma("vm:recognized", "other")
   @pragma("vm:never-inline")
diff --git a/sdk/lib/_internal/vm/lib/errors_patch.dart b/sdk/lib/_internal/vm/lib/errors_patch.dart
index 05b0afa..0c448da 100644
--- a/sdk/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/errors_patch.dart
@@ -95,7 +95,7 @@
   final Object? message;
 }
 
-class _TypeError extends Error implements TypeError, CastError {
+class _TypeError extends Error implements TypeError {
   @pragma("vm:entry-point")
   _TypeError._create(this._url, this._line, this._column, this._message);
 
@@ -112,7 +112,7 @@
   final String _message;
 }
 
-class _CastError extends Error implements CastError, TypeError {
+class _CastError extends Error implements TypeError {
   @pragma("vm:entry-point")
   _CastError._create(this._url, this._line, this._column, this._errorMsg);
 
@@ -128,6 +128,12 @@
   final String _errorMsg;
 }
 
+class _NullThrownError extends Error implements NullThrownError {
+  @pragma("vm:entry-point")
+  _NullThrownError();
+  String toString() => "Throw of null.";
+}
+
 @patch
 class FallThroughError {
   @patch
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index bdb1a01..664777c 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -140,17 +140,14 @@
 
 /// Error thrown by the runtime system when a cast operation fails.
 @Deprecated("Use TypeError instead")
-class CastError extends Error {}
+typedef CastError = TypeError;
 
 /// Error thrown when attempting to throw `null`.
 ///
 /// In null safe code, you are statically disallowed from throwing `null`,
 /// so this error will go away when non-null safe code stops being supported.
-class NullThrownError extends Error {
-  @pragma("vm:entry-point")
-  NullThrownError();
-  String toString() => "Throw of null.";
-}
+@Deprecated("Use TypeError instead")
+typedef NullThrownError = TypeError;
 
 /// Error thrown when a function is passed an unacceptable argument.
 class ArgumentError extends Error {
@@ -453,10 +450,12 @@
 
 /// Error thrown when control reaches the end of a switch case.
 ///
-/// The Dart specification requires this error to be thrown when
+/// The Dart specification required this error to be thrown when
 /// control reaches the end of a switch case (except the last case
 /// of a switch) without meeting a break or similar end of the control
 /// flow.
+/// Fallthrough has been made a compile-time error in Dart 2.0.
+@Deprecated("No longer relevant in Dart 2.0")
 class FallThroughError extends Error {
   FallThroughError();
   @pragma("vm:entry-point")
@@ -608,8 +607,8 @@
 /// Error thrown when a lazily initialized variable cannot be initialized.
 ///
 /// This is no longer used in null safe Dart code and is replaced by late
-/// variables and `LateInitializationError`.
-// TODO: Deprecate?
+/// variables which do not specify the error they throw when misused.
+@Deprecated("Not needed by null safe code")
 class CyclicInitializationError extends Error {
   final String? variableName;
   @pragma("vm:entry-point")
diff --git a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
index 8cb6e4a..c94b2ca 100644
--- a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
+++ b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
@@ -6,8 +6,8 @@
 import 'dart:async';
 
 class C {
-  C operator*(int? other) => this;
-  Object? operator-() => null;
+  C operator *(int? other) => this;
+  Object? operator -() => null;
 }
 
 // Test ambiguous cases of trailing "!" syntax.  Where possible, we verify that
@@ -18,11 +18,10 @@
   // `throw a!` means `throw (a!)`, not `(throw a)!`.  Since it's a compile-time
   // error for a thrown expression to be potentially nullable, this is
   // sufficient to verify that the compiler has resolved the ambiguity
-  // correctly.  We check the runtime behavior by verifying that the error that
-  // is thrown is not `NullThrownError`.
+  // correctly.
   Expect.throws(() {
-      throw a!;
-    }, (error) => error is! NullThrownError);
+    throw a!;
+  });
 
   // `() => a!` means `() => (a!)`, not `(() => a)!`.  We check the compile-time
   // behavior by trying to assign to a function returning non-null.  We check
@@ -31,7 +30,7 @@
   var x1 = () => a!;
   Object Function() x2 = x1;
   Expect.throws(() {
-      x1();
+    x1();
   });
 
   // `x = a!` means `x = (a!)`, not `(x = a)!`.  We check the compile-time
@@ -40,11 +39,11 @@
   // assignment occurs.
   Object x3 = 0;
   Expect.throws(() {
-      x3 = a!;
+    x3 = a!;
   });
   var x4 = 0 as Object?;
   Expect.throws(() {
-      x4 = a!;
+    x4 = a!;
   });
   Expect.equals(x4, 0);
 
@@ -66,7 +65,7 @@
   var x7 = new C();
   i = null;
   Expect.throws(() {
-      x7 * i!;
+    x7 * i!;
   });
 
   // `-x!` means `-(x!)`, not `(-x)!`.  We check the compile-time behavior by
diff --git a/tools/VERSION b/tools/VERSION
index 0ab344f..c988903 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 192
+PRERELEASE 193
 PRERELEASE_PATCH 0
\ No newline at end of file