add some very hacky caching for the analyzer macro implementation
diff --git a/pkgs/_analyzer_macros/lib/macro_implementation.dart b/pkgs/_analyzer_macros/lib/macro_implementation.dart
index e2441ce..ee744ce 100644
--- a/pkgs/_analyzer_macros/lib/macro_implementation.dart
+++ b/pkgs/_analyzer_macros/lib/macro_implementation.dart
@@ -135,6 +135,7 @@
         }
       }
       if (response == null) {
+        print('invalidated, re-running');
         _impl._host.hostService.startTracking();
         response = await _impl._host.augment(
             name,
@@ -195,6 +196,7 @@
       }
 
       if (response == null) {
+        print('invalidated, re-running');
         _impl._host.hostService.startTracking();
         response = await _impl._host.augment(
             name,
@@ -252,6 +254,7 @@
         }
       }
       if (response == null) {
+        print('invalidated, re-running');
         _impl._host.hostService.startTracking();
         response = await _impl._host.augment(
             name,
diff --git a/pkgs/dart_model/lib/dart_model.dart b/pkgs/dart_model/lib/dart_model.dart
index 4251c5e..f4ce292 100644
--- a/pkgs/dart_model/lib/dart_model.dart
+++ b/pkgs/dart_model/lib/dart_model.dart
@@ -2,16 +2,8 @@
 // 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 'src/dart_model.dart';
-
 export 'src/dart_model.dart';
 export 'src/lazy_merged_map.dart' show MergeModels;
 export 'src/scopes.dart';
 export 'src/type.dart';
 export 'src/type_system.dart';
-
-/// TODO: Mass hack alert! Mass hack alert!
-extension ModelIdentity on Model {
-  int get identityHash => 2;
-  bool equals(Model other) => true;
-}
diff --git a/pkgs/dart_model/lib/src/dart_model.g.dart b/pkgs/dart_model/lib/src/dart_model.g.dart
index cc5d9ab..2420e1a 100644
--- a/pkgs/dart_model/lib/src/dart_model.g.dart
+++ b/pkgs/dart_model/lib/src/dart_model.g.dart
@@ -24,9 +24,13 @@
         ));
 
   /// Augmentation code.
-  List<Code> get code => (node['code'] as List).cast();
-  int get identityHash =>
-      Object.hashAll(code.map((entry) => entry.identityHash));
+  List<Code> get code => (node['code'] as List).cast<Code>();
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['code'] as List?)
+          ?.cast<Code>()
+          ?.map((entry) => entry.identityHash) ??
+      const []);
 }
 
 enum CodeType {
@@ -79,6 +83,8 @@
     return node['value'] as String;
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -117,21 +123,33 @@
 
   /// Static type parameters introduced by this function type.
   List<StaticTypeParameterDesc> get typeParameters =>
-      (node['typeParameters'] as List).cast();
+      (node['typeParameters'] as List).cast<StaticTypeParameterDesc>();
   List<StaticTypeDesc> get requiredPositionalParameters =>
-      (node['requiredPositionalParameters'] as List).cast();
+      (node['requiredPositionalParameters'] as List).cast<StaticTypeDesc>();
   List<StaticTypeDesc> get optionalPositionalParameters =>
-      (node['optionalPositionalParameters'] as List).cast();
+      (node['optionalPositionalParameters'] as List).cast<StaticTypeDesc>();
   List<NamedFunctionTypeParameter> get namedParameters =>
-      (node['namedParameters'] as List).cast();
+      (node['namedParameters'] as List).cast<NamedFunctionTypeParameter>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        returnType.identityHash,
-        Object.hashAll(typeParameters.map((entry) => entry.identityHash)),
-        Object.hashAll(
-            requiredPositionalParameters.map((entry) => entry.identityHash)),
-        Object.hashAll(
-            optionalPositionalParameters.map((entry) => entry.identityHash)),
-        Object.hashAll(namedParameters.map((entry) => entry.identityHash)),
+        (node['returnType'] as StaticTypeDesc?)?.identityHash ?? 0,
+        Object.hashAll((node['typeParameters'] as List?)
+                ?.cast<StaticTypeParameterDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['requiredPositionalParameters'] as List?)
+                ?.cast<StaticTypeDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['optionalPositionalParameters'] as List?)
+                ?.cast<StaticTypeDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['namedParameters'] as List?)
+                ?.cast<NamedFunctionTypeParameter>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -150,20 +168,28 @@
 
   /// The expression of the annotation.
   Expression get expression => node['expression'] as Expression;
-  int get identityHash => expression.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['expression'] as Expression?)?.identityHash ?? 0;
 }
 
 /// Interface type for all declarations
 extension type Declaration._(Map<String, Object?> node) implements Object {
   /// The metadata annotations attached to this declaration.
   List<MetadataAnnotation> get metadataAnnotations =>
-      (node['metadataAnnotations'] as List).cast();
+      (node['metadataAnnotations'] as List).cast<MetadataAnnotation>();
 
   /// The properties of this declaration.
   Properties get properties => node['properties'] as Properties;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(metadataAnnotations.map((entry) => entry.identityHash)),
-        properties.identityHash,
+        Object.hashAll((node['metadataAnnotations'] as List?)
+                ?.cast<MetadataAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        (node['properties'] as Properties?)?.identityHash ?? 0,
       );
 }
 
@@ -194,12 +220,21 @@
 
   /// The type of the expression `this` when used in this interface.
   NamedTypeDesc get thisType => node['thisType'] as NamedTypeDesc;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(members.entries
-            .map((entry) => Object.hash(entry.key, entry.value.identityHash))),
-        thisType.identityHash,
-        Object.hashAll(metadataAnnotations.map((entry) => entry.identityHash)),
-        properties.identityHash,
+        Object.hashAll((node['members'] as Map?)
+                ?.cast<String, Member>()
+                ?.entries
+                .map((entry) =>
+                    Object.hash(entry.key, entry.value.identityHash)) ??
+            const []),
+        (node['thisType'] as NamedTypeDesc?)?.identityHash ?? 0,
+        Object.hashAll((node['metadataAnnotations'] as List?)
+                ?.cast<MetadataAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        (node['properties'] as Properties?)?.identityHash ?? 0,
       );
 }
 
@@ -217,8 +252,13 @@
   /// Scopes by name.
   Map<String, Interface> get scopes =>
       (node['scopes'] as Map).cast<String, Interface>();
-  int get identityHash => Object.hashAll(scopes.entries
-      .map((entry) => Object.hash(entry.key, entry.value.identityHash)));
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['scopes'] as Map?)
+          ?.cast<String, Interface>()
+          ?.entries
+          .map((entry) => Object.hash(entry.key, entry.value.identityHash)) ??
+      const []);
 }
 
 /// Member of a scope.
@@ -254,24 +294,36 @@
 
   /// The required positional parameters of this member, if it has them.
   List<StaticTypeDesc> get requiredPositionalParameters =>
-      (node['requiredPositionalParameters'] as List).cast();
+      (node['requiredPositionalParameters'] as List).cast<StaticTypeDesc>();
 
   /// The optional positional parameters of this member, if it has them.
   List<StaticTypeDesc> get optionalPositionalParameters =>
-      (node['optionalPositionalParameters'] as List).cast();
+      (node['optionalPositionalParameters'] as List).cast<StaticTypeDesc>();
 
   /// The named parameters of this member, if it has them.
   List<NamedFunctionTypeParameter> get namedParameters =>
-      (node['namedParameters'] as List).cast();
+      (node['namedParameters'] as List).cast<NamedFunctionTypeParameter>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        returnType.identityHash,
-        Object.hashAll(
-            requiredPositionalParameters.map((entry) => entry.identityHash)),
-        Object.hashAll(
-            optionalPositionalParameters.map((entry) => entry.identityHash)),
-        Object.hashAll(namedParameters.map((entry) => entry.identityHash)),
-        Object.hashAll(metadataAnnotations.map((entry) => entry.identityHash)),
-        properties.identityHash,
+        (node['returnType'] as StaticTypeDesc?)?.identityHash ?? 0,
+        Object.hashAll((node['requiredPositionalParameters'] as List?)
+                ?.cast<StaticTypeDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['optionalPositionalParameters'] as List?)
+                ?.cast<StaticTypeDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['namedParameters'] as List?)
+                ?.cast<NamedFunctionTypeParameter>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['metadataAnnotations'] as List?)
+                ?.cast<MetadataAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        (node['properties'] as Properties?)?.identityHash ?? 0,
       );
 }
 
@@ -295,11 +347,27 @@
 
   /// The resolved static type hierarchy.
   TypeHierarchy get types => node['types'] as TypeHierarchy;
-  int get identityHash => Object.hash(
-        Object.hashAll(uris.entries
-            .map((entry) => Object.hash(entry.key, entry.value.identityHash))),
-        types.identityHash,
+
+  static final watch = Stopwatch()..start();
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash {
+    watch.start();
+    try {
+      return Object.hash(
+        Object.hashAll((node['uris'] as Map?)
+                ?.cast<String, Library>()
+                ?.entries
+                .map((entry) =>
+                    Object.hash(entry.key, entry.value.identityHash)) ??
+            const []),
+        (node['types'] as TypeHierarchy?)?.identityHash ?? 0,
       );
+    } finally {
+      watch.stop();
+      print('Model.identityHash: ${watch.elapsedMilliseconds}ms');
+    }
+  }
 }
 
 /// A resolved named parameter as part of a [FunctionTypeDesc].
@@ -323,10 +391,12 @@
   String get name => node['name'] as String;
   bool get required => node['required'] as bool;
   StaticTypeDesc get type => node['type'] as StaticTypeDesc;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        name.hashCode,
-        required.hashCode,
-        type.identityHash,
+        (node['name'] as String?).hashCode,
+        (node['required'] as bool?).hashCode,
+        (node['type'] as StaticTypeDesc?)?.identityHash ?? 0,
       );
 }
 
@@ -347,9 +417,11 @@
         ));
   String get name => node['name'] as String;
   StaticTypeDesc get type => node['type'] as StaticTypeDesc;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        name.hashCode,
-        type.identityHash,
+        (node['name'] as String?).hashCode,
+        (node['type'] as StaticTypeDesc?)?.identityHash ?? 0,
       );
 }
 
@@ -370,10 +442,15 @@
         ));
   QualifiedName get name => node['name'] as QualifiedName;
   List<StaticTypeDesc> get instantiation =>
-      (node['instantiation'] as List).cast();
+      (node['instantiation'] as List).cast<StaticTypeDesc>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        name.identityHash,
-        Object.hashAll(instantiation.map((entry) => entry.identityHash)),
+        (node['name'] as QualifiedName?)?.identityHash ?? 0,
+        Object.hashAll((node['instantiation'] as List?)
+                ?.cast<StaticTypeDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -397,7 +474,9 @@
 
   /// The type T.
   StaticTypeDesc get inner => node['inner'] as StaticTypeDesc;
-  int get identityHash => inner.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['inner'] as StaticTypeDesc?)?.identityHash ?? 0;
 }
 
 /// Set of boolean properties.
@@ -451,14 +530,16 @@
 
   /// Whether the entity is static.
   bool get isStatic => node['isStatic'] as bool;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        isAbstract.hashCode,
-        isClass.hashCode,
-        isConstructor.hashCode,
-        isGetter.hashCode,
-        isField.hashCode,
-        isMethod.hashCode,
-        isStatic.hashCode,
+        (node['isAbstract'] as bool?).hashCode,
+        (node['isClass'] as bool?).hashCode,
+        (node['isConstructor'] as bool?).hashCode,
+        (node['isGetter'] as bool?).hashCode,
+        (node['isField'] as bool?).hashCode,
+        (node['isMethod'] as bool?).hashCode,
+        (node['isStatic'] as bool?).hashCode,
       );
 }
 
@@ -526,11 +607,13 @@
 
   /// Whether the name refers to something in the static scope as opposed to the instance scope of `scope`. Will be `null` if `scope` is `null`.
   bool? get isStatic => node['isStatic'] as bool?;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        uri.hashCode,
-        scope.hashCode,
-        name.hashCode,
-        isStatic.hashCode,
+        (node['uri'] as String?).hashCode,
+        (node['scope'] as String?).hashCode,
+        (node['name'] as String?).hashCode,
+        (node['isStatic'] as bool?).hashCode,
       );
 }
 
@@ -544,7 +627,9 @@
 
   /// The class to query about.
   QualifiedName get target => node['target'] as QualifiedName;
-  int get identityHash => target.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['target'] as QualifiedName?)?.identityHash ?? 0;
 }
 
 /// A resolved record type in the type hierarchy.
@@ -562,11 +647,21 @@
           positional,
           named,
         ));
-  List<StaticTypeDesc> get positional => (node['positional'] as List).cast();
-  List<NamedRecordField> get named => (node['named'] as List).cast();
+  List<StaticTypeDesc> get positional =>
+      (node['positional'] as List).cast<StaticTypeDesc>();
+  List<NamedRecordField> get named =>
+      (node['named'] as List).cast<NamedRecordField>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(positional.map((entry) => entry.identityHash)),
-        Object.hashAll(named.map((entry) => entry.identityHash)),
+        Object.hashAll((node['positional'] as List?)
+                ?.cast<StaticTypeDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['named'] as List?)
+                ?.cast<NamedRecordField>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -720,6 +815,8 @@
     return VoidTypeDesc.fromJson(node['value'] as Null);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -740,9 +837,11 @@
         ));
   int get identifier => node['identifier'] as int;
   StaticTypeDesc? get bound => node['bound'] as StaticTypeDesc?;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        identifier.hashCode,
-        bound?.identityHash ?? 0,
+        (node['identifier'] as int?).hashCode,
+        (node['bound'] as StaticTypeDesc?)?.identityHash ?? 0,
       );
 }
 
@@ -761,8 +860,13 @@
   /// Map of qualified interface names to their resolved named type.
   Map<String, TypeHierarchyEntry> get named =>
       (node['named'] as Map).cast<String, TypeHierarchyEntry>();
-  int get identityHash => Object.hashAll(named.entries
-      .map((entry) => Object.hash(entry.key, entry.value.identityHash)));
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['named'] as Map?)
+          ?.cast<String, TypeHierarchyEntry>()
+          ?.entries
+          .map((entry) => Object.hash(entry.key, entry.value.identityHash)) ??
+      const []);
 }
 
 /// Entry of an interface in Dart's type hierarchy, along with supertypes.
@@ -786,17 +890,26 @@
 
   /// Type parameters defined on this interface-defining element.
   List<StaticTypeParameterDesc> get typeParameters =>
-      (node['typeParameters'] as List).cast();
+      (node['typeParameters'] as List).cast<StaticTypeParameterDesc>();
 
   /// The named static type represented by this entry.
   NamedTypeDesc get self => node['self'] as NamedTypeDesc;
 
   /// All direct supertypes of this type.
-  List<NamedTypeDesc> get supertypes => (node['supertypes'] as List).cast();
+  List<NamedTypeDesc> get supertypes =>
+      (node['supertypes'] as List).cast<NamedTypeDesc>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(typeParameters.map((entry) => entry.identityHash)),
-        self.identityHash,
-        Object.hashAll(supertypes.map((entry) => entry.identityHash)),
+        Object.hashAll((node['typeParameters'] as List?)
+                ?.cast<StaticTypeParameterDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        (node['self'] as NamedTypeDesc?)?.identityHash ?? 0,
+        Object.hashAll((node['supertypes'] as List?)
+                ?.cast<NamedTypeDesc>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -813,7 +926,9 @@
           parameterId,
         ));
   int get parameterId => node['parameterId'] as int;
-  int get identityHash => parameterId.hashCode;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['parameterId'] as int?).hashCode;
 }
 
 /// The type-hierarchy representation of the type `void`.
diff --git a/pkgs/dart_model/lib/src/macro_metadata.g.dart b/pkgs/dart_model/lib/src/macro_metadata.g.dart
index 901b91d..242af55 100644
--- a/pkgs/dart_model/lib/src/macro_metadata.g.dart
+++ b/pkgs/dart_model/lib/src/macro_metadata.g.dart
@@ -59,6 +59,8 @@
     return NamedArgument.fromJson(node['value'] as Map<String, Object?>);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -145,6 +147,8 @@
     return IfElement.fromJson(node['value'] as Map<String, Object?>);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -706,6 +710,8 @@
     return UnresolvedExpression.fromJson(node['value'] as Map<String, Object?>);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -763,6 +769,8 @@
         node['value'] as Map<String, Object?>);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -950,6 +958,8 @@
         node['value'] as Map<String, Object?>);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -1006,6 +1016,8 @@
     return InterpolationPart.fromJson(node['value'] as Map<String, Object?>);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -1188,6 +1200,8 @@
     return RecordTypeAnnotation.fromJson(node['value'] as Map<String, Object?>);
   }
 
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -1217,6 +1231,8 @@
       BinaryOperator.fromJson('bitwiseAnd');
   static const BinaryOperator bitwiseXor =
       BinaryOperator.fromJson('bitwiseXor');
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => string.hashCode;
 }
 
@@ -1224,6 +1240,8 @@
 extension type const LogicalOperator.fromJson(String string) implements Object {
   static const LogicalOperator and = LogicalOperator.fromJson('and');
   static const LogicalOperator or = LogicalOperator.fromJson('or');
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => string.hashCode;
 }
 
@@ -1232,6 +1250,8 @@
   static const UnaryOperator minus = UnaryOperator.fromJson('minus');
   static const UnaryOperator bang = UnaryOperator.fromJson('bang');
   static const UnaryOperator tilde = UnaryOperator.fromJson('tilde');
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => string.hashCode;
 }
 
@@ -1256,9 +1276,11 @@
 
   ///
   TypeAnnotation get type => node['type'] as TypeAnnotation;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        expression.identityHash,
-        type.identityHash,
+        (node['expression'] as Expression?)?.identityHash ?? 0,
+        (node['type'] as TypeAnnotation?)?.identityHash ?? 0,
       );
 }
 
@@ -1289,10 +1311,12 @@
 
   ///
   Expression get right => node['right'] as Expression;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        left.identityHash,
-        operator.identityHash,
-        right.identityHash,
+        (node['left'] as Expression?)?.identityHash ?? 0,
+        (node['operator'] as BinaryOperator?)?.identityHash ?? 0,
+        (node['right'] as Expression?)?.identityHash ?? 0,
       );
 }
 
@@ -1311,7 +1335,9 @@
 
   ///
   String get text => node['text'] as String;
-  int get identityHash => text.hashCode;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['text'] as String?).hashCode;
 }
 
 ///
@@ -1322,6 +1348,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1352,10 +1380,12 @@
 
   ///
   Expression get otherwise => node['otherwise'] as Expression;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        condition.identityHash,
-        then.identityHash,
-        otherwise.identityHash,
+        (node['condition'] as Expression?)?.identityHash ?? 0,
+        (node['then'] as Expression?)?.identityHash ?? 0,
+        (node['otherwise'] as Expression?)?.identityHash ?? 0,
       );
 }
 
@@ -1385,11 +1415,16 @@
   Reference get constructor => node['constructor'] as Reference;
 
   ///
-  List<Argument> get arguments => (node['arguments'] as List).cast();
+  List<Argument> get arguments => (node['arguments'] as List).cast<Argument>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        type.identityHash,
-        constructor.identityHash,
-        Object.hashAll(arguments.map((entry) => entry.identityHash)),
+        (node['type'] as TypeAnnotation?)?.identityHash ?? 0,
+        (node['constructor'] as Reference?)?.identityHash ?? 0,
+        Object.hashAll((node['arguments'] as List?)
+                ?.cast<Argument>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -1401,6 +1436,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1426,9 +1463,11 @@
   ///
   ConstructorReference get reference =>
       node['reference'] as ConstructorReference;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        type.identityHash,
-        reference.identityHash,
+        (node['type'] as TypeAnnotation?)?.identityHash ?? 0,
+        (node['reference'] as ConstructorReference?)?.identityHash ?? 0,
       );
 }
 
@@ -1447,7 +1486,9 @@
 
   ///
   String get text => node['text'] as String;
-  int get identityHash => text.hashCode;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['text'] as String?).hashCode;
 }
 
 ///
@@ -1465,7 +1506,9 @@
 
   ///
   Reference get reference => node['reference'] as Reference;
-  int get identityHash => reference.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['reference'] as Reference?)?.identityHash ?? 0;
 }
 
 ///
@@ -1476,6 +1519,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1506,10 +1551,12 @@
 
   ///
   bool get isNotEquals => node['isNotEquals'] as bool;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        left.identityHash,
-        right.identityHash,
-        isNotEquals.hashCode,
+        (node['left'] as Expression?)?.identityHash ?? 0,
+        (node['right'] as Expression?)?.identityHash ?? 0,
+        (node['isNotEquals'] as bool?).hashCode,
       );
 }
 
@@ -1534,9 +1581,11 @@
 
   ///
   bool get isNullAware => node['isNullAware'] as bool;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        expression.identityHash,
-        isNullAware.hashCode,
+        (node['expression'] as Expression?)?.identityHash ?? 0,
+        (node['isNullAware'] as bool?).hashCode,
       );
 }
 
@@ -1548,6 +1597,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1559,6 +1610,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1570,6 +1623,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1581,6 +1636,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1592,6 +1649,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1603,6 +1662,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1621,7 +1682,10 @@
 
   ///
   FunctionReference get reference => node['reference'] as FunctionReference;
-  int get identityHash => reference.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['reference'] as FunctionReference?)?.identityHash ?? 0;
 }
 
 ///
@@ -1648,15 +1712,23 @@
 
   ///
   List<FunctionTypeParameter> get typeParameters =>
-      (node['typeParameters'] as List).cast();
+      (node['typeParameters'] as List).cast<FunctionTypeParameter>();
 
   ///
   List<FormalParameter> get formalParameters =>
-      (node['formalParameters'] as List).cast();
+      (node['formalParameters'] as List).cast<FormalParameter>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        returnType?.identityHash ?? 0,
-        Object.hashAll(typeParameters.map((entry) => entry.identityHash)),
-        Object.hashAll(formalParameters.map((entry) => entry.identityHash)),
+        (node['returnType'] as TypeAnnotation?)?.identityHash ?? 0,
+        Object.hashAll((node['typeParameters'] as List?)
+                ?.cast<FunctionTypeParameter>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['formalParameters'] as List?)
+                ?.cast<FormalParameter>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -1668,6 +1740,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1679,6 +1753,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1698,7 +1774,11 @@
   ///
   FunctionTypeParameter get functionTypeParameter =>
       node['functionTypeParameter'] as FunctionTypeParameter;
-  int get identityHash => functionTypeParameter.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['functionTypeParameter'] as FunctionTypeParameter?)?.identityHash ??
+      0;
 }
 
 ///
@@ -1727,10 +1807,12 @@
 
   ///
   Element? get otherwise => node['otherwise'] as Element?;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        condition.identityHash,
-        then.identityHash,
-        otherwise?.identityHash ?? 0,
+        (node['condition'] as Expression?)?.identityHash ?? 0,
+        (node['then'] as Element?)?.identityHash ?? 0,
+        (node['otherwise'] as Element?)?.identityHash ?? 0,
       );
 }
 
@@ -1754,9 +1836,11 @@
 
   ///
   Expression get right => node['right'] as Expression;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        left.identityHash,
-        right.identityHash,
+        (node['left'] as Expression?)?.identityHash ?? 0,
+        (node['right'] as Expression?)?.identityHash ?? 0,
       );
 }
 
@@ -1784,14 +1868,22 @@
 
   ///
   List<TypeAnnotation> get typeArguments =>
-      (node['typeArguments'] as List).cast();
+      (node['typeArguments'] as List).cast<TypeAnnotation>();
 
   ///
-  List<Argument> get arguments => (node['arguments'] as List).cast();
+  List<Argument> get arguments => (node['arguments'] as List).cast<Argument>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        receiver.identityHash,
-        Object.hashAll(typeArguments.map((entry) => entry.identityHash)),
-        Object.hashAll(arguments.map((entry) => entry.identityHash)),
+        (node['receiver'] as Expression?)?.identityHash ?? 0,
+        Object.hashAll((node['typeArguments'] as List?)
+                ?.cast<TypeAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['arguments'] as List?)
+                ?.cast<Argument>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -1816,10 +1908,15 @@
 
   ///
   List<TypeAnnotation> get typeArguments =>
-      (node['typeArguments'] as List).cast();
+      (node['typeArguments'] as List).cast<TypeAnnotation>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        receiver.identityHash,
-        Object.hashAll(typeArguments.map((entry) => entry.identityHash)),
+        (node['receiver'] as Expression?)?.identityHash ?? 0,
+        Object.hashAll((node['typeArguments'] as List?)
+                ?.cast<TypeAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -1838,7 +1935,9 @@
 
   ///
   String get text => node['text'] as String;
-  int get identityHash => text.hashCode;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['text'] as String?).hashCode;
 }
 
 ///
@@ -1856,7 +1955,10 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
-  int get identityHash => expression.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['expression'] as Expression?)?.identityHash ?? 0;
 }
 
 ///
@@ -1867,6 +1969,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1878,6 +1982,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -1907,10 +2013,12 @@
 
   ///
   bool get isNot => node['isNot'] as bool;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        expression.identityHash,
-        type.identityHash,
-        isNot.hashCode,
+        (node['expression'] as Expression?)?.identityHash ?? 0,
+        (node['type'] as TypeAnnotation?)?.identityHash ?? 0,
+        (node['isNot'] as bool?).hashCode,
       );
 }
 
@@ -1932,13 +2040,21 @@
 
   ///
   List<TypeAnnotation> get typeArguments =>
-      (node['typeArguments'] as List).cast();
+      (node['typeArguments'] as List).cast<TypeAnnotation>();
 
   ///
-  List<Element> get elements => (node['elements'] as List).cast();
+  List<Element> get elements => (node['elements'] as List).cast<Element>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(typeArguments.map((entry) => entry.identityHash)),
-        Object.hashAll(elements.map((entry) => entry.identityHash)),
+        Object.hashAll((node['typeArguments'] as List?)
+                ?.cast<TypeAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['elements'] as List?)
+                ?.cast<Element>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -1969,10 +2085,12 @@
 
   ///
   Expression get right => node['right'] as Expression;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        left.identityHash,
-        operator.identityHash,
-        right.identityHash,
+        (node['left'] as Expression?)?.identityHash ?? 0,
+        (node['operator'] as LogicalOperator?)?.identityHash ?? 0,
+        (node['right'] as Expression?)?.identityHash ?? 0,
       );
 }
 
@@ -2009,11 +2127,13 @@
 
   ///
   bool get isNullAwareValue => node['isNullAwareValue'] as bool;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        key.identityHash,
-        value.identityHash,
-        isNullAwareKey.hashCode,
-        isNullAwareValue.hashCode,
+        (node['key'] as Expression?)?.identityHash ?? 0,
+        (node['value'] as Expression?)?.identityHash ?? 0,
+        (node['isNullAwareKey'] as bool?).hashCode,
+        (node['isNullAwareValue'] as bool?).hashCode,
       );
 }
 
@@ -2047,15 +2167,23 @@
 
   ///
   List<TypeAnnotation> get typeArguments =>
-      (node['typeArguments'] as List).cast();
+      (node['typeArguments'] as List).cast<TypeAnnotation>();
 
   ///
-  List<Argument> get arguments => (node['arguments'] as List).cast();
+  List<Argument> get arguments => (node['arguments'] as List).cast<Argument>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        receiver.identityHash,
-        name.hashCode,
-        Object.hashAll(typeArguments.map((entry) => entry.identityHash)),
-        Object.hashAll(arguments.map((entry) => entry.identityHash)),
+        (node['receiver'] as Expression?)?.identityHash ?? 0,
+        (node['name'] as String?).hashCode,
+        Object.hashAll((node['typeArguments'] as List?)
+                ?.cast<TypeAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['arguments'] as List?)
+                ?.cast<Argument>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -2080,9 +2208,11 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        name.hashCode,
-        expression.identityHash,
+        (node['name'] as String?).hashCode,
+        (node['expression'] as Expression?)?.identityHash ?? 0,
       );
 }
 
@@ -2107,10 +2237,15 @@
 
   ///
   List<TypeAnnotation> get typeArguments =>
-      (node['typeArguments'] as List).cast();
+      (node['typeArguments'] as List).cast<TypeAnnotation>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        reference.identityHash,
-        Object.hashAll(typeArguments.map((entry) => entry.identityHash)),
+        (node['reference'] as Reference?)?.identityHash ?? 0,
+        Object.hashAll((node['typeArguments'] as List?)
+                ?.cast<TypeAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -2129,7 +2264,10 @@
 
   ///
   TypeAnnotation get typeAnnotation => node['typeAnnotation'] as TypeAnnotation;
-  int get identityHash => typeAnnotation.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['typeAnnotation'] as TypeAnnotation?)?.identityHash ?? 0;
 }
 
 ///
@@ -2153,9 +2291,11 @@
 
   ///
   String get name => node['name'] as String;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        receiver.identityHash,
-        name.hashCode,
+        (node['receiver'] as Expression?)?.identityHash ?? 0,
+        (node['name'] as String?).hashCode,
       );
 }
 
@@ -2173,7 +2313,10 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
-  int get identityHash => expression.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['expression'] as Expression?)?.identityHash ?? 0;
 }
 
 ///
@@ -2184,6 +2327,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -2202,7 +2347,10 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
-  int get identityHash => expression.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['expression'] as Expression?)?.identityHash ?? 0;
 }
 
 ///
@@ -2220,7 +2368,10 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
-  int get identityHash => expression.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['expression'] as Expression?)?.identityHash ?? 0;
 }
 
 ///
@@ -2244,9 +2395,11 @@
 
   ///
   String get name => node['name'] as String;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        receiver.identityHash,
-        name.hashCode,
+        (node['receiver'] as Expression?)?.identityHash ?? 0,
+        (node['name'] as String?).hashCode,
       );
 }
 
@@ -2264,9 +2417,13 @@
         ));
 
   ///
-  List<RecordField> get fields => (node['fields'] as List).cast();
-  int get identityHash =>
-      Object.hashAll(fields.map((entry) => entry.identityHash));
+  List<RecordField> get fields => (node['fields'] as List).cast<RecordField>();
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['fields'] as List?)
+          ?.cast<RecordField>()
+          ?.map((entry) => entry.identityHash) ??
+      const []);
 }
 
 ///
@@ -2290,9 +2447,11 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        name.hashCode,
-        expression.identityHash,
+        (node['name'] as String?).hashCode,
+        (node['expression'] as Expression?)?.identityHash ?? 0,
       );
 }
 
@@ -2311,7 +2470,10 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
-  int get identityHash => expression.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['expression'] as Expression?)?.identityHash ?? 0;
 }
 
 ///
@@ -2331,13 +2493,23 @@
         ));
 
   ///
-  List<RecordTypeEntry> get positional => (node['positional'] as List).cast();
+  List<RecordTypeEntry> get positional =>
+      (node['positional'] as List).cast<RecordTypeEntry>();
 
   ///
-  List<RecordTypeEntry> get named => (node['named'] as List).cast();
+  List<RecordTypeEntry> get named =>
+      (node['named'] as List).cast<RecordTypeEntry>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(positional.map((entry) => entry.identityHash)),
-        Object.hashAll(named.map((entry) => entry.identityHash)),
+        Object.hashAll((node['positional'] as List?)
+                ?.cast<RecordTypeEntry>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['named'] as List?)
+                ?.cast<RecordTypeEntry>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -2349,6 +2521,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -2360,6 +2534,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -2381,13 +2557,21 @@
 
   ///
   List<TypeAnnotation> get typeArguments =>
-      (node['typeArguments'] as List).cast();
+      (node['typeArguments'] as List).cast<TypeAnnotation>();
 
   ///
-  List<Element> get elements => (node['elements'] as List).cast();
+  List<Element> get elements => (node['elements'] as List).cast<Element>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(typeArguments.map((entry) => entry.identityHash)),
-        Object.hashAll(elements.map((entry) => entry.identityHash)),
+        Object.hashAll((node['typeArguments'] as List?)
+                ?.cast<TypeAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['elements'] as List?)
+                ?.cast<Element>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -2412,9 +2596,11 @@
 
   ///
   bool get isNullAware => node['isNullAware'] as bool;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        expression.identityHash,
-        isNullAware.hashCode,
+        (node['expression'] as Expression?)?.identityHash ?? 0,
+        (node['isNullAware'] as bool?).hashCode,
       );
 }
 
@@ -2432,7 +2618,10 @@
 
   ///
   FieldReference get reference => node['reference'] as FieldReference;
-  int get identityHash => reference.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['reference'] as FieldReference?)?.identityHash ?? 0;
 }
 
 ///
@@ -2459,14 +2648,22 @@
 
   ///
   List<TypeAnnotation> get typeArguments =>
-      (node['typeArguments'] as List).cast();
+      (node['typeArguments'] as List).cast<TypeAnnotation>();
 
   ///
-  List<Argument> get arguments => (node['arguments'] as List).cast();
+  List<Argument> get arguments => (node['arguments'] as List).cast<Argument>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        function.identityHash,
-        Object.hashAll(typeArguments.map((entry) => entry.identityHash)),
-        Object.hashAll(arguments.map((entry) => entry.identityHash)),
+        (node['function'] as FunctionReference?)?.identityHash ?? 0,
+        Object.hashAll((node['typeArguments'] as List?)
+                ?.cast<TypeAnnotation>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
+        Object.hashAll((node['arguments'] as List?)
+                ?.cast<Argument>()
+                ?.map((entry) => entry.identityHash) ??
+            const []),
       );
 }
 
@@ -2484,9 +2681,14 @@
         ));
 
   ///
-  List<Expression> get expressions => (node['expressions'] as List).cast();
-  int get identityHash =>
-      Object.hashAll(expressions.map((entry) => entry.identityHash));
+  List<Expression> get expressions =>
+      (node['expressions'] as List).cast<Expression>();
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['expressions'] as List?)
+          ?.cast<Expression>()
+          ?.map((entry) => entry.identityHash) ??
+      const []);
 }
 
 ///
@@ -2503,9 +2705,14 @@
         ));
 
   ///
-  List<StringLiteralPart> get parts => (node['parts'] as List).cast();
-  int get identityHash =>
-      Object.hashAll(parts.map((entry) => entry.identityHash));
+  List<StringLiteralPart> get parts =>
+      (node['parts'] as List).cast<StringLiteralPart>();
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['parts'] as List?)
+          ?.cast<StringLiteralPart>()
+          ?.map((entry) => entry.identityHash) ??
+      const []);
 }
 
 ///
@@ -2523,7 +2730,9 @@
 
   ///
   String get text => node['text'] as String;
-  int get identityHash => text.hashCode;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['text'] as String?).hashCode;
 }
 
 ///
@@ -2540,8 +2749,13 @@
         ));
 
   ///
-  List<String> get parts => (node['parts'] as List).cast();
-  int get identityHash => Object.hashAll(parts.map((entry) => entry.hashCode));
+  List<String> get parts => (node['parts'] as List).cast<String>();
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['parts'] as List?)
+          ?.cast<String>()
+          ?.map((entry) => entry.hashCode) ??
+      const []);
 }
 
 ///
@@ -2552,6 +2766,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -2570,7 +2786,10 @@
 
   ///
   TypeAnnotation get typeAnnotation => node['typeAnnotation'] as TypeAnnotation;
-  int get identityHash => typeAnnotation.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['typeAnnotation'] as TypeAnnotation?)?.identityHash ?? 0;
 }
 
 ///
@@ -2581,6 +2800,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -2605,9 +2826,11 @@
 
   ///
   Expression get expression => node['expression'] as Expression;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        operator.identityHash,
-        expression.identityHash,
+        (node['operator'] as UnaryOperator?)?.identityHash ?? 0,
+        (node['expression'] as Expression?)?.identityHash ?? 0,
       );
 }
 
@@ -2619,6 +2842,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -2630,6 +2855,8 @@
       : this.fromJson(Scope.createMap(
           _schema,
         ));
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -2648,5 +2875,7 @@
 
   ///
   Reference get reference => node['reference'] as Reference;
-  int get identityHash => reference.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['reference'] as Reference?)?.identityHash ?? 0;
 }
diff --git a/pkgs/macro_service/lib/src/handshake.g.dart b/pkgs/macro_service/lib/src/handshake.g.dart
index b66ae27..6e8b32c 100644
--- a/pkgs/macro_service/lib/src/handshake.g.dart
+++ b/pkgs/macro_service/lib/src/handshake.g.dart
@@ -18,9 +18,13 @@
         });
 
   /// Supported protocols.
-  List<Protocol> get protocols => (node['protocols'] as List).cast();
-  int get identityHash =>
-      Object.hashAll(protocols.map((entry) => entry.identityHash));
+  List<Protocol> get protocols => (node['protocols'] as List).cast<Protocol>();
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => Object.hashAll((node['protocols'] as List?)
+          ?.cast<Protocol>()
+          ?.map((entry) => entry.identityHash) ??
+      const []);
 }
 
 /// The picked protocol, or `null` if no requested protocol is supported.
@@ -34,7 +38,9 @@
 
   /// Supported protocol.
   Protocol? get protocol => node['protocol'] as Protocol?;
-  int get identityHash => protocol?.identityHash ?? 0;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['protocol'] as Protocol?)?.identityHash ?? 0;
 }
 
 /// The macro to host protocol version and encoding. TODO(davidmorgan): add the version.
@@ -56,9 +62,11 @@
 
   /// The protocol version, a name and number.
   ProtocolVersion get version => node['version'] as ProtocolVersion;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        encoding.identityHash,
-        version.identityHash,
+        (node['encoding'] as ProtocolEncoding?)?.identityHash ?? 0,
+        (node['version'] as ProtocolVersion?)?.identityHash ?? 0,
       );
 }
 
@@ -67,6 +75,8 @@
     implements Object {
   static const ProtocolEncoding json = ProtocolEncoding.fromJson('json');
   static const ProtocolEncoding binary = ProtocolEncoding.fromJson('binary');
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => string.hashCode;
 }
 
@@ -75,5 +85,7 @@
   static const ProtocolVersion handshake =
       ProtocolVersion.fromJson('handshake');
   static const ProtocolVersion macros1 = ProtocolVersion.fromJson('macros1');
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => string.hashCode;
 }
diff --git a/pkgs/macro_service/lib/src/macro_service.g.dart b/pkgs/macro_service/lib/src/macro_service.g.dart
index 3d76b96..d3350c3 100644
--- a/pkgs/macro_service/lib/src/macro_service.g.dart
+++ b/pkgs/macro_service/lib/src/macro_service.g.dart
@@ -31,10 +31,12 @@
 
   /// A pre-computed query result for the target.
   Model get model => node['model'] as Model;
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        phase.hashCode,
-        target.identityHash,
-        model.identityHash,
+        (node['phase'] as int?).hashCode,
+        (node['target'] as QualifiedName?)?.identityHash ?? 0,
+        (node['model'] as Model?)?.identityHash ?? 0,
       );
 }
 
@@ -58,67 +60,94 @@
   /// Any augmentations to enum values that should be applied to an enum as a result of executing a macro, indexed by the name of the enum.
   Map<String, List<Augmentation>>? get enumValueAugmentations =>
       (node['enumValueAugmentations'] as Map?)
-          ?.deepCast<String, List<Augmentation>>((v) => (v as List).cast());
+          ?.deepCast<String, List<Augmentation>>(
+              (v) => (v as List).cast<Augmentation>());
 
   /// Any extends clauses that should be added to types as a result of executing a macro, indexed by the name of the augmented type declaration.
   Map<String, List<Augmentation>>? get extendsTypeAugmentations =>
       (node['extendsTypeAugmentations'] as Map?)
-          ?.deepCast<String, List<Augmentation>>((v) => (v as List).cast());
+          ?.deepCast<String, List<Augmentation>>(
+              (v) => (v as List).cast<Augmentation>());
 
   /// Any interfaces that should be added to types as a result of executing a macro, indexed by the name of the augmented type declaration.
   Map<String, List<Augmentation>>? get interfaceAugmentations =>
       (node['interfaceAugmentations'] as Map?)
-          ?.deepCast<String, List<Augmentation>>((v) => (v as List).cast());
+          ?.deepCast<String, List<Augmentation>>(
+              (v) => (v as List).cast<Augmentation>());
 
   /// Any augmentations that should be applied to the library as a result of executing a macro.
   List<Augmentation>? get libraryAugmentations =>
-      (node['libraryAugmentations'] as List?)?.cast();
+      (node['libraryAugmentations'] as List?)?.cast<Augmentation>();
 
   /// Any mixins that should be added to types as a result of executing a macro, indexed by the name of the augmented type declaration.
   Map<String, List<Augmentation>>? get mixinAugmentations =>
       (node['mixinAugmentations'] as Map?)
-          ?.deepCast<String, List<Augmentation>>((v) => (v as List).cast());
+          ?.deepCast<String, List<Augmentation>>(
+              (v) => (v as List).cast<Augmentation>());
 
   /// The names of any new types declared in [libraryAugmentations].
-  List<String>? get newTypeNames => (node['newTypeNames'] as List?)?.cast();
+  List<String>? get newTypeNames =>
+      (node['newTypeNames'] as List?)?.cast<String>();
 
   /// Any augmentations that should be applied to a class as a result of executing a macro, indexed by the name of the class.
   Map<String, List<Augmentation>>? get typeAugmentations =>
-      (node['typeAugmentations'] as Map?)
-          ?.deepCast<String, List<Augmentation>>((v) => (v as List).cast());
+      (node['typeAugmentations'] as Map?)?.deepCast<String, List<Augmentation>>(
+          (v) => (v as List).cast<Augmentation>());
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        Object.hashAll(enumValueAugmentations?.entries.map((entry) =>
-                Object.hash(
+        Object.hashAll((node['enumValueAugmentations'] as Map?)
+                ?.deepCast<String, List<Augmentation>>(
+                    (v) => (v as List).cast<Augmentation>())
+                ?.entries
+                .map((entry) => Object.hash(
                     entry.key,
                     Object.hashAll(
                         entry.value.map((entry) => entry.identityHash)))) ??
             const []),
-        Object.hashAll(extendsTypeAugmentations?.entries.map((entry) =>
-                Object.hash(
+        Object.hashAll((node['extendsTypeAugmentations'] as Map?)
+                ?.deepCast<String, List<Augmentation>>(
+                    (v) => (v as List).cast<Augmentation>())
+                ?.entries
+                .map((entry) => Object.hash(
                     entry.key,
                     Object.hashAll(
                         entry.value.map((entry) => entry.identityHash)))) ??
             const []),
-        Object.hashAll(interfaceAugmentations?.entries.map((entry) =>
-                Object.hash(
+        Object.hashAll((node['interfaceAugmentations'] as Map?)
+                ?.deepCast<String, List<Augmentation>>(
+                    (v) => (v as List).cast<Augmentation>())
+                ?.entries
+                .map((entry) => Object.hash(
                     entry.key,
                     Object.hashAll(
                         entry.value.map((entry) => entry.identityHash)))) ??
             const []),
-        Object.hashAll(
-            libraryAugmentations?.map((entry) => entry.identityHash) ??
-                const []),
-        Object.hashAll(mixinAugmentations?.entries.map((entry) => Object.hash(
-                entry.key,
-                Object.hashAll(
-                    entry.value.map((entry) => entry.identityHash)))) ??
+        Object.hashAll((node['libraryAugmentations'] as List?)
+                ?.cast<Augmentation>()
+                ?.map((entry) => entry.identityHash) ??
             const []),
-        Object.hashAll(
-            newTypeNames?.map((entry) => entry.hashCode) ?? const []),
-        Object.hashAll(typeAugmentations?.entries.map((entry) => Object.hash(
-                entry.key,
-                Object.hashAll(
-                    entry.value.map((entry) => entry.identityHash)))) ??
+        Object.hashAll((node['mixinAugmentations'] as Map?)
+                ?.deepCast<String, List<Augmentation>>(
+                    (v) => (v as List).cast<Augmentation>())
+                ?.entries
+                .map((entry) => Object.hash(
+                    entry.key,
+                    Object.hashAll(
+                        entry.value.map((entry) => entry.identityHash)))) ??
+            const []),
+        Object.hashAll((node['newTypeNames'] as List?)
+                ?.cast<String>()
+                ?.map((entry) => entry.hashCode) ??
+            const []),
+        Object.hashAll((node['typeAugmentations'] as Map?)
+                ?.deepCast<String, List<Augmentation>>(
+                    (v) => (v as List).cast<Augmentation>())
+                ?.entries
+                .map((entry) => Object.hash(
+                    entry.key,
+                    Object.hashAll(
+                        entry.value.map((entry) => entry.identityHash)))) ??
             const []),
       );
 }
@@ -134,7 +163,9 @@
 
   /// The error.
   String get error => node['error'] as String;
-  int get identityHash => error.hashCode;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['error'] as String?).hashCode;
 }
 
 /// A macro host server endpoint. TODO(davidmorgan): this should be a oneOf supporting different types of connection. TODO(davidmorgan): it's not clear if this belongs in this package! But, where else?
@@ -148,7 +179,9 @@
 
   /// TCP port to connect to.
   int get port => node['port'] as int;
-  int get identityHash => port.hashCode;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['port'] as int?).hashCode;
 }
 
 enum HostRequestType {
@@ -193,6 +226,9 @@
 
   /// The annotation identifying the macro that should handle the request.
   QualifiedName get macroAnnotation => node['macroAnnotation'] as QualifiedName;
+
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -211,10 +247,15 @@
   QualifiedName get annotation => node['annotation'] as QualifiedName;
 
   /// Phases that the macro runs in: 1, 2 and/or 3.
-  List<int> get runsInPhases => (node['runsInPhases'] as List).cast();
+  List<int> get runsInPhases => (node['runsInPhases'] as List).cast<int>();
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => Object.hash(
-        annotation.identityHash,
-        Object.hashAll(runsInPhases.map((entry) => entry.hashCode)),
+        (node['annotation'] as QualifiedName?)?.identityHash ?? 0,
+        Object.hashAll((node['runsInPhases'] as List?)
+                ?.cast<int>()
+                ?.map((entry) => entry.hashCode) ??
+            const []),
       );
 }
 
@@ -230,13 +271,18 @@
   /// The macro description.
   MacroDescription get macroDescription =>
       node['macroDescription'] as MacroDescription;
-  int get identityHash => macroDescription.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash =>
+      (node['macroDescription'] as MacroDescription?)?.identityHash ?? 0;
 }
 
 /// Host's response to a [MacroStartedRequest].
 extension type MacroStartedResponse.fromJson(Map<String, Object?> node)
     implements Object {
   MacroStartedResponse() : this.fromJson({});
+
+  /// Hash code for comparing instances of this extension type.
   int get identityHash => 0;
 }
 
@@ -296,6 +342,9 @@
 
   /// The id of this request, must be returned in responses.
   int get id => node['id'] as int;
+
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
 
@@ -310,7 +359,9 @@
 
   /// The query.
   Query get query => node['query'] as Query;
-  int get identityHash => query.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['query'] as Query?)?.identityHash ?? 0;
 }
 
 /// Host's response to a [QueryRequest].
@@ -324,7 +375,9 @@
 
   /// The model.
   Model get model => node['model'] as Model;
-  int get identityHash => model.identityHash;
+
+  /// Hash code for comparing instances of this extension type.
+  int get identityHash => (node['model'] as Model?)?.identityHash ?? 0;
 }
 
 enum ResponseType {
@@ -420,5 +473,8 @@
 
   /// The id of the request this is responding to.
   int get requestId => node['requestId'] as int;
+
+  /// Hash code for comparing instances of this extension type.
+// TODO: A real implementation for union types.
   int get identityHash => 0;
 }
diff --git a/tool/dart_model_generator/lib/generate_dart_model.dart b/tool/dart_model_generator/lib/generate_dart_model.dart
index 613665a..8901d23 100644
--- a/tool/dart_model_generator/lib/generate_dart_model.dart
+++ b/tool/dart_model_generator/lib/generate_dart_model.dart
@@ -369,7 +369,9 @@
       return '($rawCast)$q.deepCast<String, ${elementType!.dartType}>('
           '(v) => ${elementType!.castExpression('v')})';
     } else if (isList) {
-      if (elementType!.elementType == null) return '($rawCast)$q.cast()';
+      if (elementType!.elementType == null) {
+        return '($rawCast)$q.cast<${elementType!.dartType}>()';
+      }
       throw UnsupportedError('Deep casting for lists isn\'t yet supported.');
     } else {
       return rawCast;
@@ -622,8 +624,12 @@
         _ => throw StateError('Unreachable'),
       });
     for (final property in allProperties(context)) {
-      final hashExpr = property.type
-          .hashExpression(property.name, nullable: property.nullable);
+      var castExpr = property.type
+          .castExpression("node['${property.name}']", nullable: true);
+      if (!castExpr.endsWith(')')) {
+        castExpr = '($castExpr)';
+      }
+      final hashExpr = property.type.hashExpression(castExpr, nullable: true);
       result.writeln('$hashExpr${numProperties > 1 ? ', ' : ''}');
     }
     result.writeln(switch (numProperties) {