Version 2.15.0-31.0.dev

Merge commit '8997a8991449e9e23d78126cd576a17dd4008280' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index fe960e4..e70c308 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -220,7 +220,7 @@
       "name": "dart2js_tools",
       "rootUri": "../pkg/dart2js_tools",
       "packageUri": "lib/",
-      "languageVersion": "2.12"
+      "languageVersion": "2.3"
     },
     {
       "name": "dart2native",
@@ -812,4 +812,4 @@
       "languageVersion": "2.12"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 80e7594..f24ee78 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 170;
+  static const int DATA_VERSION = 171;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 9a9dd13..c558f5a 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -59,6 +59,8 @@
         return _readConstructorFieldInitializer();
       case Tag.ConstructorName:
         return _readConstructorName();
+      case Tag.ConstructorReference:
+        return _readConstructorReference();
       case Tag.DeclaredIdentifier:
         return _readDeclaredIdentifier();
       case Tag.DefaultFormalParameter:
@@ -337,6 +339,15 @@
     return node;
   }
 
+  ConstructorReference _readConstructorReference() {
+    var constructorName = readNode() as ConstructorName;
+    var node = astFactory.constructorReference(
+      constructorName: constructorName,
+    );
+    _readExpressionResolution(node);
+    return node;
+  }
+
   SimpleIdentifierImpl _readDeclarationName() {
     var name = _reader.readStringReference();
     return astFactory.simpleIdentifier(
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
index deb6b47..b82d1aa 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
@@ -34,6 +34,7 @@
   static const int ConditionalExpression = 51;
   static const int ConstructorFieldInitializer = 50;
   static const int ConstructorName = 7;
+  static const int ConstructorReference = 101;
   static const int DeclaredIdentifier = 90;
   static const int DefaultFormalParameter = 8;
   static const int DottedName = 47;
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index e5dca3f..d6b5e0c 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -173,6 +173,13 @@
   }
 
   @override
+  void visitConstructorReference(ConstructorReference node) {
+    _writeByte(Tag.ConstructorReference);
+    _writeNode(node.constructorName);
+    _storeExpression(node);
+  }
+
+  @override
   void visitDeclaredIdentifier(DeclaredIdentifier node) {
     _writeByte(Tag.DeclaredIdentifier);
     _writeByte(
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index afbe147..e495081 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -367,6 +367,17 @@
   }
 
   @override
+  void visitConstructorReference(ConstructorReference node) {
+    _writeln('ConstructorReference');
+    _withIndent(() {
+      var properties = _Properties();
+      properties.addNode('constructorName', node.constructorName);
+      _addExpression(properties, node);
+      _writeProperties(properties);
+    });
+  }
+
+  @override
   void visitContinueStatement(ContinueStatement node) {
     _writeNextCodeLine(node);
     _writeln('ContinueStatement');
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index e434353..8427857 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -100,6 +100,11 @@
     sdkLanguageVersion: Version.parse('2.13.0'),
     flags: [EnableString.generic_metadata],
   );
+
+  static final FeatureSet constructorTearOffs = FeatureSet.fromEnableFlags2(
+    sdkLanguageVersion: Version.parse('2.15.0'),
+    flags: [EnableString.constructor_tearoffs],
+  );
 }
 
 /// Mixin containing test cases exercising summary resynthesis.  Intended to be
@@ -6306,6 +6311,48 @@
     _assertTypeStr(yType, 'C<int>');
   }
 
+  test_const_constructorReference() async {
+    featureSet = FeatureSets.constructorTearOffs;
+    var library = await checkLibrary(r'''
+class A {
+  A.named();
+}
+const v = A.named;
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class A @6
+        constructors
+          named @14
+            periodOffset: 13
+            nameEnd: 19
+    topLevelVariables
+      static const v @31
+        type: A Function()
+        constantInitializer
+          ConstructorReference
+            constructorName: ConstructorName
+              name: SimpleIdentifier
+                staticElement: self::@class::A::@constructor::named
+                staticType: null
+                token: named @37
+              period: . @36
+              staticElement: self::@class::A::@constructor::named
+              type: TypeName
+                name: SimpleIdentifier
+                  staticElement: self::@class::A
+                  staticType: null
+                  token: A @35
+                type: A
+            staticType: A Function()
+    accessors
+      synthetic static get v @-1
+        returnType: A Function()
+''');
+  }
+
   test_const_finalField_hasConstConstructor() async {
     var library = await checkLibrary(r'''
 class C {
diff --git a/pkg/dart2js_tools/bin/deobfuscate.dart b/pkg/dart2js_tools/bin/deobfuscate.dart
index adecc1b..d6ba837 100644
--- a/pkg/dart2js_tools/bin/deobfuscate.dart
+++ b/pkg/dart2js_tools/bin/deobfuscate.dart
@@ -47,24 +47,24 @@
   var sb = new StringBuffer();
   try {
     String obfuscatedTrace = new File(args[0]).readAsStringSync();
-    String? error = extractErrorMessage(obfuscatedTrace);
+    String error = extractErrorMessage(obfuscatedTrace);
     var provider = new CachingFileProvider(logger: Logger());
     StackDeobfuscationResult result =
         deobfuscateStack(obfuscatedTrace, provider);
     Frame firstFrame = result.original.frames.first;
-    String? translatedError =
+    String translatedError =
         translate(error, provider.mappingFor(firstFrame.uri));
     if (translatedError == null) translatedError = '<no error message found>';
     printPadded(translatedError, error, sb);
     int longest =
-        result.deobfuscated.frames.fold(0, (m, f) => max(f.member!.length, m));
+        result.deobfuscated.frames.fold(0, (m, f) => max(f.member.length, m));
     for (var originalFrame in result.original.frames) {
       var deobfuscatedFrames = result.frameMap[originalFrame];
       if (deobfuscatedFrames == null) {
         printPadded('no mapping', '${originalFrame.location}', sb);
       } else {
         for (var frame in deobfuscatedFrames) {
-          printPadded('${frame.member!.padRight(longest)} ${frame.location}',
+          printPadded('${frame.member.padRight(longest)} ${frame.location}',
               '${originalFrame.location}', sb);
         }
       }
@@ -77,7 +77,7 @@
 final green = stdout.hasTerminal ? '\x1b[32m' : '';
 final none = stdout.hasTerminal ? '\x1b[0m' : '';
 
-printPadded(String mapping, String? original, sb) {
+printPadded(String mapping, String original, sb) {
   var len = mapping.length;
   var s = mapping.indexOf('\n');
   if (s >= 0) len -= s + 1;
diff --git a/pkg/dart2js_tools/bin/lookup_name.dart b/pkg/dart2js_tools/bin/lookup_name.dart
index b0fbfe9..f2d5c1b 100644
--- a/pkg/dart2js_tools/bin/lookup_name.dart
+++ b/pkg/dart2js_tools/bin/lookup_name.dart
@@ -2,7 +2,6 @@
 import 'dart:convert';
 import 'package:source_maps/source_maps.dart';
 import 'package:dart2js_tools/src/dart2js_mapping.dart';
-import 'package:dart2js_tools/src/util.dart';
 
 main(List<String> args) {
   if (args.length < 2) {
@@ -17,7 +16,7 @@
     exit(1);
   }
   var json = jsonDecode(sourcemapFile.readAsStringSync());
-  Dart2jsMapping mapping = Dart2jsMapping(parseSingleMapping(json), json);
+  Dart2jsMapping mapping = Dart2jsMapping(parseJson(json), json);
   var global = mapping.globalNames[name];
   if (global != null) print('$name => $global (a global name)');
   var instance = mapping.instanceNames[name];
diff --git a/pkg/dart2js_tools/bin/show_inline_data.dart b/pkg/dart2js_tools/bin/show_inline_data.dart
index a83531f..cc3d5f0 100644
--- a/pkg/dart2js_tools/bin/show_inline_data.dart
+++ b/pkg/dart2js_tools/bin/show_inline_data.dart
@@ -26,7 +26,7 @@
   var offsets = frames.keys.toList()..sort();
   var sb = new StringBuffer();
   int depth = 0;
-  int? lastFunctionStart = null;
+  int lastFunctionStart = null;
   for (var offset in offsets) {
     int functionStart = nextFunctionStart(starts, offset, lastFunctionStart);
     if (lastFunctionStart == null || functionStart > lastFunctionStart) {
@@ -43,7 +43,7 @@
     var pad = ' ' * offsetPrefix.length;
     sb.write(offsetPrefix);
     bool first = true;
-    for (var frame in frames[offset]!) {
+    for (var frame in frames[offset]) {
       if (!first) sb.write('$pad');
       sb.write(' $frame\n');
       first = false;
@@ -75,7 +75,7 @@
   return result;
 }
 
-int nextFunctionStart(List<int> starts, int offset, int? last) {
+int nextFunctionStart(List<int> starts, int offset, int last) {
   int j = last ?? 0;
   for (; j < starts.length && starts[j] <= offset; j++);
   return j - 1;
diff --git a/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart b/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart
index f93d751..29a209e 100644
--- a/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart
+++ b/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart
@@ -27,7 +27,7 @@
 ///  `//# sourceMappingURL=` line at the end, and load the corresponding
 /// source-map file.
 String deobfuscateStackTrace(String obfuscatedTrace) {
-  String? error = extractErrorMessage(obfuscatedTrace);
+  String error = extractErrorMessage(obfuscatedTrace);
   var provider = CachingFileProvider();
   StackDeobfuscationResult result = deobfuscateStack(obfuscatedTrace, provider);
   Frame firstFrame = result.original.frames.first;
@@ -38,13 +38,13 @@
 
   var sb = StringBuffer();
   sb.writeln(translatedError);
-  maxMemberLengthHelper(int m, Frame f) => max(f.member!.length, m);
+  maxMemberLengthHelper(int m, Frame f) => max(f.member.length, m);
   int longest = result.deobfuscated.frames.fold(0, maxMemberLengthHelper);
   longest = result.original.frames.fold(longest, maxMemberLengthHelper);
   for (var originalFrame in result.original.frames) {
     var deobfuscatedFrames = result.frameMap[originalFrame];
     if (deobfuscatedFrames == null) {
-      var name = originalFrame.member!;
+      var name = originalFrame.member;
       sb.writeln('    at ${name.padRight(longest)} ${originalFrame.location}');
     } else {
       for (var frame in deobfuscatedFrames) {
@@ -53,7 +53,7 @@
         // client, we can start encoding the function name and remove this
         // workaround.
         if (name == '<unknown>') name = originalFrame.member;
-        sb.writeln('    at ${name!.padRight(longest)} ${frame.location}');
+        sb.writeln('    at ${name.padRight(longest)} ${frame.location}');
       }
     }
   }
diff --git a/pkg/dart2js_tools/lib/src/dart2js_mapping.dart b/pkg/dart2js_tools/lib/src/dart2js_mapping.dart
index 8f67882..ac6b9d7 100644
--- a/pkg/dart2js_tools/lib/src/dart2js_mapping.dart
+++ b/pkg/dart2js_tools/lib/src/dart2js_mapping.dart
@@ -23,9 +23,15 @@
   final Map<String, String> globalNames = {};
   final Map<String, String> instanceNames = {};
   final Map<int, List<FrameEntry>> frames = {};
-  late final List<int>? frameIndex = frames.keys.toList()..sort();
+  List<int> _frameIndex;
+  List<int> get frameIndex {
+    if (_frameIndex == null) {
+      _frameIndex = frames.keys.toList()..sort();
+    }
+    return _frameIndex;
+  }
 
-  Dart2jsMapping(this.sourceMap, Map json, {Logger? logger}) {
+  Dart2jsMapping(this.sourceMap, Map json, {Logger logger}) {
     var extensions = json['x_org_dartlang_dart2js'];
     if (extensions == null) return;
     var minifiedNames = extensions['minified_names'];
@@ -35,20 +41,20 @@
       _extractMinifedNames(
           minifiedNames['instance'], sourceMap, instanceNames, logger);
     }
-    String? jsonFrames = extensions['frames'];
+    String jsonFrames = extensions['frames'];
     if (jsonFrames != null) {
       new _FrameDecoder(jsonFrames).parseFrames(frames, sourceMap);
     }
   }
 
-  Dart2jsMapping.json(Map json) : this(parseSingleMapping(json), json);
+  Dart2jsMapping.json(Map json) : this(parseJson(json), json);
 }
 
 class FrameEntry {
-  final String? callUri;
-  final int? callLine;
-  final int? callColumn;
-  final String? inlinedMethodName;
+  final String callUri;
+  final int callLine;
+  final int callColumn;
+  final String inlinedMethodName;
   final bool isEmpty;
   FrameEntry.push(
       this.callUri, this.callLine, this.callColumn, this.inlinedMethodName)
@@ -70,7 +76,7 @@
 }
 
 const _marker = "\n//# sourceMappingURL=";
-Dart2jsMapping? parseMappingFor(Uri uri, {Logger? logger}) {
+Dart2jsMapping parseMappingFor(Uri uri, {Logger logger}) {
   var file = new File.fromUri(uri);
   if (!file.existsSync()) {
     logger?.log('Error: no such file: $uri');
@@ -94,7 +100,7 @@
     return null;
   }
   var json = jsonDecode(sourcemapFile.readAsStringSync());
-  return new Dart2jsMapping(parseSingleMapping(json), json, logger: logger);
+  return new Dart2jsMapping(parseJson(json), json, logger: logger);
 }
 
 class _FrameDecoder implements Iterator<String> {
@@ -106,9 +112,8 @@
   // Iterator API is used by decodeVlq to consume VLQ entries.
   bool moveNext() => ++index < _length;
 
-  String get current => (index >= 0 && index < _length)
-      ? _internal[index]
-      : throw StateError('No current value available.');
+  String get current =>
+      (index >= 0 && index < _length) ? _internal[index] : null;
 
   bool get hasTokens => index < _length - 1 && _length > 0;
 
@@ -146,7 +151,7 @@
 }
 
 _extractMinifedNames(String encodedInput, SingleMapping sourceMap,
-    Map<String, String> minifiedNames, Logger? logger) {
+    Map<String, String> minifiedNames, Logger logger) {
   if (encodedInput.isEmpty) return;
   List<String> input = encodedInput.split(',');
   if (input.length % 2 != 0) {
@@ -154,7 +159,7 @@
   }
   for (int i = 0; i < input.length; i += 2) {
     String minifiedName = input[i];
-    int id = int.tryParse(input[i + 1])!;
+    int id = int.tryParse(input[i + 1]);
     minifiedNames[minifiedName] = sourceMap.names[id];
   }
 }
diff --git a/pkg/dart2js_tools/lib/src/name_decoder.dart b/pkg/dart2js_tools/lib/src/name_decoder.dart
index 458fd60..306bead 100644
--- a/pkg/dart2js_tools/lib/src/name_decoder.dart
+++ b/pkg/dart2js_tools/lib/src/name_decoder.dart
@@ -9,8 +9,8 @@
 import 'dart2js_mapping.dart';
 import 'trace.dart';
 
-String? translate(String? error, Dart2jsMapping mapping,
-    [StackTraceLine? line, TargetEntry? entry]) {
+String translate(String error, Dart2jsMapping mapping,
+    [StackTraceLine line, TargetEntry entry]) {
   for (var decoder in _errorMapDecoders) {
     var result = decoder.decode(error, mapping, line, entry);
     // More than one decoder might be applied on a single error message. This
@@ -30,10 +30,10 @@
   /// Decode [error] that was reported in [line] and has a corresponding [entry]
   /// in the source-map file. The provided [mapping] includes additional
   /// minification data that may be used to decode the error message.
-  String? decode(String? error, Dart2jsMapping mapping, StackTraceLine? line,
-      TargetEntry? entry) {
+  String decode(String error, Dart2jsMapping mapping, StackTraceLine line,
+      TargetEntry entry) {
     if (error == null) return null;
-    Match? lastMatch = null;
+    Match lastMatch = null;
     var result = new StringBuffer();
     for (var match in _matcher.allMatches(error)) {
       var decodedMatch = _decodeInternal(match, mapping, line, entry);
@@ -49,8 +49,8 @@
     return '$result';
   }
 
-  String? _decodeInternal(Match match, Dart2jsMapping mapping,
-      StackTraceLine? line, TargetEntry? entry);
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry);
 }
 
 typedef String ErrorDecoder(Match match, Dart2jsMapping mapping,
@@ -59,28 +59,28 @@
 class MinifiedNameDecoder extends ErrorMapDecoder {
   final RegExp _matcher = new RegExp("minified:([a-zA-Z0-9_\$]*)");
 
-  String? _decodeInternal(Match match, Dart2jsMapping mapping,
-      StackTraceLine? line, TargetEntry? entry) {
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
     var minifiedName = match.group(1);
-    return mapping.globalNames[minifiedName!];
+    return mapping.globalNames[minifiedName];
   }
 }
 
 class CannotReadPropertyDecoder extends ErrorMapDecoder {
   final RegExp _matcher = new RegExp("Cannot read property '([^']*)' of");
 
-  String? _decodeInternal(Match match, Dart2jsMapping mapping,
-      StackTraceLine? line, TargetEntry? entry) {
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
     var minifiedName = match.group(1);
-    var name = mapping.instanceNames[minifiedName!];
+    var name = mapping.instanceNames[minifiedName];
     if (name == null) return null;
     return "Cannot read property '$name' of";
   }
 }
 
 abstract class NoSuchMethodDecoderBase extends ErrorMapDecoder {
-  String? _translateMinifiedName(Dart2jsMapping mapping, String? minifiedName) {
-    var name = mapping.instanceNames[minifiedName!];
+  String _translateMinifiedName(Dart2jsMapping mapping, String minifiedName) {
+    var name = mapping.instanceNames[minifiedName];
     if (name != null) return "'$name'";
     if (minifiedName.startsWith(new RegExp(r'(call)?\$[0-9]'))) {
       int first$ = minifiedName.indexOf(r'$');
@@ -89,15 +89,15 @@
     return null;
   }
 
-  String? _expandCallSignature(String callSignature) {
+  String _expandCallSignature(String callSignature) {
     // Minified names are one of these forms:
     //   $0         // positional arguments only
     //   $1$2       // type parameters and positional arguments
     //   $3$name    // positional and named arguments
     //   $1$3$name  // type parameters and positional and named args
     var signature = callSignature.split(r'$');
-    int? typeArgs = null;
-    int? totalArgs = null;
+    var typeArgs = null;
+    var totalArgs = null;
     var namedArgs = <String>[];
     for (var arg in signature) {
       if (arg == "") continue;
@@ -115,7 +115,6 @@
         namedArgs.add(arg);
       }
     }
-    if (totalArgs == null) return null;
     var sb = new StringBuffer();
     sb.write("'call'");
     sb.write(" (with ");
@@ -137,8 +136,8 @@
   final RegExp _matcher = new RegExp(
       "NoSuchMethodError: method not found: '([^']*)'( on [^\\(]*)? \\(.*\\)");
 
-  String? _decodeInternal(Match match, Dart2jsMapping mapping,
-      StackTraceLine? line, TargetEntry? entry) {
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
     var minifiedName = match.group(1);
     var suffix = match.group(2) ?? '';
     var name = _translateMinifiedName(mapping, minifiedName);
@@ -151,8 +150,8 @@
   final RegExp _matcher =
       new RegExp("NoSuchMethodError: method not found: '([^']*)'");
 
-  String? _decodeInternal(Match match, Dart2jsMapping mapping,
-      StackTraceLine? line, TargetEntry? entry) {
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
     var minifiedName = match.group(1);
     var name = _translateMinifiedName(mapping, minifiedName);
     if (name == null) return null;
@@ -163,10 +162,10 @@
 class UnhandledNotAFunctionError extends ErrorMapDecoder {
   final RegExp _matcher = new RegExp("Error: ([^']*) is not a function");
 
-  String? _decodeInternal(Match match, Dart2jsMapping mapping,
-      StackTraceLine? line, TargetEntry? entry) {
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
     var minifiedName = match.group(1);
-    var name = mapping.instanceNames[minifiedName!];
+    var name = mapping.instanceNames[minifiedName];
     if (name == null) return null;
     return "Error: $name is not a function";
   }
diff --git a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
index 87b0c40..68ffd94 100644
--- a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
+++ b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
@@ -10,7 +10,7 @@
 
 /// Search backwards in [sources] for a function declaration that includes the
 /// [start] offset.
-TargetEntry? findEnclosingFunction(FileProvider provider, Uri uri, int start) {
+TargetEntry findEnclosingFunction(FileProvider provider, Uri uri, int start) {
   String sources = provider.sourcesFor(uri);
   if (sources == null) return null;
   SourceFile file = provider.fileFor(uri);
@@ -22,7 +22,7 @@
     var line = file.getLine(index);
     var lineEntry = findLine(mapping, line);
     var column = file.getColumn(index);
-    TargetEntry? result = findColumn(line, column, lineEntry);
+    TargetEntry result = findColumn(line, column, lineEntry);
     // If the name entry doesn't start exactly at the column corresponding to
     // `index`, we must be in the middle of a string or code that uses the word
     // "function", but that doesn't have a corresponding mapping. In those
@@ -61,7 +61,7 @@
 /// number is lower or equal to [line].
 ///
 /// Copied from [SingleMapping._findLine].
-TargetLineEntry? findLine(SingleMapping sourceMap, int line) {
+TargetLineEntry findLine(SingleMapping sourceMap, int line) {
   int index = binarySearch(sourceMap.lines, (e) => e.line > line);
   return (index <= 0) ? null : sourceMap.lines[index - 1];
 }
@@ -73,7 +73,7 @@
 /// the very last entry on that line.
 ///
 /// Copied from [SingleMapping._findColumn].
-TargetEntry? findColumn(int line, int column, TargetLineEntry? lineEntry) {
+TargetEntry findColumn(int line, int column, TargetLineEntry lineEntry) {
   if (lineEntry == null || lineEntry.entries.length == 0) return null;
   if (lineEntry.line != line) return lineEntry.entries.last;
   var entries = lineEntry.entries;
diff --git a/pkg/dart2js_tools/lib/src/trace.dart b/pkg/dart2js_tools/lib/src/trace.dart
index 07bdb1e..846af16 100644
--- a/pkg/dart2js_tools/lib/src/trace.dart
+++ b/pkg/dart2js_tools/lib/src/trace.dart
@@ -14,10 +14,10 @@
 
 /// Represents a stack trace line.
 class StackTraceLine {
-  final String? methodName;
-  final String fileName;
-  final int? lineNo;
-  final int columnNo;
+  String methodName;
+  String fileName;
+  int lineNo;
+  int columnNo;
 
   StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo);
 
@@ -31,11 +31,11 @@
   ///     at <fileName>:<lineNo>
   ///     at <fileName>
   ///
-  factory StackTraceLine.fromText(String text, {Logger? logger}) {
+  factory StackTraceLine.fromText(String text, {Logger logger}) {
     text = text.trim();
     assert(text.startsWith('at '));
     text = text.substring('at '.length);
-    String? methodName;
+    String methodName;
     int endParen = text.indexOf(')');
     if (endParen > 0) {
       int nameEnd = text.indexOf('(');
@@ -46,16 +46,16 @@
         logger?.log('Missing left-paren in: $text');
       }
     }
-    int? lineNo;
-    int? columnNo;
+    int lineNo;
+    int columnNo;
     String fileName;
     int lastColon = text.lastIndexOf(':');
     if (lastColon != -1) {
-      int? lastValue = int.tryParse(text.substring(lastColon + 1));
+      int lastValue = int.tryParse(text.substring(lastColon + 1));
       if (lastValue != null) {
         int secondToLastColon = text.lastIndexOf(':', lastColon - 1);
         if (secondToLastColon != -1) {
-          int? secondToLastValue =
+          int secondToLastValue =
               int.tryParse(text.substring(secondToLastColon + 1, lastColon));
           if (secondToLastValue != null) {
             lineNo = secondToLastValue;
@@ -84,14 +84,14 @@
     if (methodName != null) {
       sb.write(methodName);
       sb.write(' (');
-      sb.write(fileName);
+      sb.write(fileName ?? '?');
       sb.write(':');
       sb.write(lineNo);
       sb.write(':');
       sb.write(columnNo);
       sb.write(')');
     } else {
-      sb.write(fileName);
+      sb.write(fileName ?? '?');
       sb.write(':');
       sb.write(lineNo);
       sb.write(':');
@@ -103,27 +103,27 @@
   String get inlineString {
     StringBuffer sb = new StringBuffer();
     var padding = 20;
-    var lineMethodName = methodName;
-    if (lineMethodName != null) {
-      sb.write(lineMethodName);
-      padding -= (lineMethodName.length);
+    if (methodName != null) {
+      sb.write(methodName);
+      padding -= (methodName.length);
       if (padding <= 0) {
         sb.write('\n');
         padding = 20;
       }
     }
     sb.write(' ' * padding);
-    sb.write(p.url.basename(fileName));
-    sb.write(' ');
-    sb.write(lineNo);
-    sb.write(':');
-    sb.write(columnNo);
-
+    if (fileName != null) {
+      sb.write(p.url.basename(fileName));
+      sb.write(' ');
+      sb.write(lineNo);
+      sb.write(':');
+      sb.write(columnNo);
+    }
     return sb.toString();
   }
 }
 
-List<StackTraceLine> parseStackTrace(String trace, {Logger? logger}) {
+List<StackTraceLine> parseStackTrace(String trace, {Logger logger}) {
   List<String> lines = trace.split(new RegExp(r'(\r|\n|\r\n)'));
   List<StackTraceLine> jsStackTrace = <StackTraceLine>[];
   for (String line in lines) {
@@ -138,7 +138,7 @@
 /// Returns the portion of the output that corresponds to the error message.
 ///
 /// Note: some errors can span multiple lines.
-String? extractErrorMessage(String trace) {
+String extractErrorMessage(String trace) {
   var firstStackFrame = trace.indexOf(new RegExp('\n +at'));
   if (firstStackFrame == -1) return null;
   var errorMarker = trace.indexOf('^') + 1;
diff --git a/pkg/dart2js_tools/lib/src/trace_decoder.dart b/pkg/dart2js_tools/lib/src/trace_decoder.dart
index 5699423..7ac12aa 100644
--- a/pkg/dart2js_tools/lib/src/trace_decoder.dart
+++ b/pkg/dart2js_tools/lib/src/trace_decoder.dart
@@ -49,8 +49,8 @@
 
     // Subtract 1 because stack traces use 1-indexed lines and columns and
     // source maps uses 0-indexed.
-    SourceSpan? span = mapping.sourceMap
-        .spanFor(frame.line! - 1, column - 1, uri: frame.uri.toString());
+    SourceSpan span = mapping.sourceMap
+        .spanFor(frame.line - 1, column - 1, uri: frame.uri?.toString());
 
     // If we can't find a source span, ignore the frame. It's probably something
     // internal that the user doesn't care about.
@@ -59,11 +59,11 @@
     List<Frame> mappedFrames = frameMap[frame] = [];
 
     SourceFile jsFile = provider.fileFor(frame.uri);
-    int offset = jsFile.getOffset(frame.line! - 1, column - 1);
+    int offset = jsFile.getOffset(frame.line - 1, column - 1);
     String nameOf(id) =>
         _normalizeName(id >= 0 ? mapping.sourceMap.names[id] : null);
 
-    Uri? fileName = span.sourceUrl;
+    Uri fileName = span.sourceUrl;
     int targetLine = span.start.line + 1;
     int targetColumn = span.start.column + 1;
 
@@ -73,18 +73,18 @@
     // of the caller frame until we reach the actual function that dart2js
     // inlined all the code into.
     Map<int, List<FrameEntry>> frames = mapping.frames;
-    List<int> index = mapping.frameIndex!;
+    List<int> index = mapping.frameIndex;
     int key = binarySearch(index, (i) => i > offset) - 1;
     int depth = 0;
     outer:
     while (key >= 0) {
-      for (var frame in frames[index[key]]!.reversed) {
+      for (var frame in frames[index[key]].reversed) {
         if (frame.isEmpty) break outer;
         if (frame.isPush) {
           if (depth <= 0) {
-            mappedFrames.add(new Frame(fileName!, targetLine, targetColumn,
+            mappedFrames.add(new Frame(fileName, targetLine, targetColumn,
                 _normalizeName(frame.inlinedMethodName) + "(inlined)"));
-            fileName = Uri.parse(frame.callUri!);
+            fileName = Uri.parse(frame.callUri);
             targetLine = (frame.callLine ?? 0) + 1;
             targetColumn = (frame.callColumn ?? 0) + 1;
           } else {
@@ -100,8 +100,7 @@
 
     var functionEntry = findEnclosingFunction(provider, frame.uri, offset);
     String methodName = nameOf(functionEntry?.sourceNameId ?? -1);
-    mappedFrames
-        .add(new Frame(fileName!, targetLine, targetColumn, methodName));
+    mappedFrames.add(new Frame(fileName, targetLine, targetColumn, methodName));
     deobfuscatedFrames.addAll(mappedFrames);
   }
   return new StackDeobfuscationResult(
@@ -110,6 +109,6 @@
 
 /// Ensure we don't use spaces in method names. At this time, they are only
 /// introduced by `<anonymous function>`.
-_normalizeName(String? methodName) =>
+_normalizeName(String methodName) =>
     methodName?.replaceAll("<anonymous function>", "<anonymous>") ??
     '<unknown>';
diff --git a/pkg/dart2js_tools/lib/src/util.dart b/pkg/dart2js_tools/lib/src/util.dart
index 3bd0ab9..433ac5a 100644
--- a/pkg/dart2js_tools/lib/src/util.dart
+++ b/pkg/dart2js_tools/lib/src/util.dart
@@ -1,5 +1,4 @@
 import 'dart:io';
-import 'package:source_maps/parser.dart';
 import 'package:source_span/source_span.dart';
 import 'dart2js_mapping.dart';
 
@@ -13,7 +12,7 @@
   final Map<Uri, String> _sources = {};
   final Map<Uri, SourceFile> _files = {};
   final Map<Uri, Dart2jsMapping> _mappings = {};
-  final Logger? logger;
+  final Logger logger;
 
   CachingFileProvider({this.logger});
 
@@ -24,7 +23,7 @@
       _files[uri] ??= new SourceFile.fromString(sourcesFor(uri));
 
   Dart2jsMapping mappingFor(Uri uri) =>
-      _mappings[uri] ??= parseMappingFor(uri, logger: logger)!;
+      _mappings[uri] ??= parseMappingFor(uri, logger: logger);
 }
 
 /// A provider that converts `http:` URLs to a `file:` URI assuming that all
@@ -58,5 +57,3 @@
 }
 
 var logger = Logger();
-
-SingleMapping parseSingleMapping(Map json) => parseJson(json) as SingleMapping;
diff --git a/pkg/dart2js_tools/pubspec.yaml b/pkg/dart2js_tools/pubspec.yaml
index e7f1642..0d28868 100644
--- a/pkg/dart2js_tools/pubspec.yaml
+++ b/pkg/dart2js_tools/pubspec.yaml
@@ -10,4 +10,4 @@
   source_span: any
   stack_trace: ^1.9.3
 environment:
-  sdk: '2.12.0 <3.0.0'
+  sdk: '>=2.3.0 <3.0.0'
diff --git a/pkg/front_end/tool/ast_model.dart b/pkg/front_end/tool/ast_model.dart
index 74d8cf2..a0708e4 100644
--- a/pkg/front_end/tool/ast_model.dart
+++ b/pkg/front_end/tool/ast_model.dart
@@ -2,8 +2,6 @@
 // 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
-
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart';
 import 'package:front_end/src/api_prototype/front_end.dart';
 import 'package:front_end/src/api_prototype/kernel_generator.dart';
@@ -33,7 +31,7 @@
 /// If the identifying name is non-null, this is used to determine the
 /// nominality. For instance the name of a variable declaration is taking as
 /// defining its identity.
-const Map<String, String> _declarativeClassesNames = const {
+const Map<String, String?> _declarativeClassesNames = const {
   'VariableDeclaration': 'name',
   'TypeParameter': 'name',
   'LabeledStatement': null,
@@ -82,7 +80,7 @@
 /// [FieldRule] define exceptions to how a field should be treated.
 ///
 /// If a field name maps to `null`, the field is not included in the [AstModel].
-const Map<String /*?*/, Map<String, FieldRule /*?*/ >> _fieldRuleMap = {
+const Map<String?, Map<String, FieldRule?>> _fieldRuleMap = {
   null: {
     'hashCode': null,
     'parent': null,
@@ -192,29 +190,29 @@
   ///
   /// This is for instance used for private fields accessed through a public
   /// getter.
-  final String name;
+  final String? name;
 
   /// For fields contain ast class of kind `AstClassKind.declarative`, this
   /// value defines whether the field should be treated as a declaration or
   /// a reference to the declaration.
-  final bool isDeclaration;
+  final bool? isDeclaration;
 
   const FieldRule({this.name, this.isDeclaration});
 }
 
 /// Return the [FieldRule] to use for the [field] in [AstClass].
-FieldRule getFieldRule(AstClass astClass, Field field) {
+FieldRule? getFieldRule(AstClass astClass, Field field) {
   String name = field.name.text;
-  Map<String, FieldRule> leafClassMap = _fieldRuleMap[astClass.name];
+  Map<String?, FieldRule?>? leafClassMap = _fieldRuleMap[astClass.name];
   if (leafClassMap != null && leafClassMap.containsKey(name)) {
     return leafClassMap[name];
   }
-  Map<String, FieldRule> enclosingClassMap =
-      _fieldRuleMap[field.enclosingClass.name];
+  Map<String?, FieldRule?>? enclosingClassMap =
+      _fieldRuleMap[field.enclosingClass!.name];
   if (enclosingClassMap != null && enclosingClassMap.containsKey(name)) {
     return enclosingClassMap[name];
   }
-  Map<String, FieldRule> defaultClassMap = _fieldRuleMap[null];
+  Map<String?, FieldRule?>? defaultClassMap = _fieldRuleMap[null];
   if (defaultClassMap != null && defaultClassMap.containsKey(name)) {
     return defaultClassMap[name];
   }
@@ -275,26 +273,25 @@
 
 class AstClass {
   final Class node;
-  AstClassKind _kind;
-  final String declarativeName;
+  AstClassKind? _kind;
+  final String? declarativeName;
   final bool isInterchangeable;
 
-  AstClass superclass;
+  AstClass? superclass;
   List<AstClass> interfaces = [];
   List<AstClass> subclasses = [];
   List<AstClass> subtypes = [];
 
-  List<AstField> fields = [];
+  Map<String, AstField> fields = {};
 
   AstClass(this.node,
       {this.superclass,
-      AstClassKind kind,
+      AstClassKind? kind,
       this.declarativeName,
-      this.isInterchangeable})
-      : _kind = kind,
-        assert(isInterchangeable != null) {
+      required this.isInterchangeable})
+      : _kind = kind {
     if (superclass != null) {
-      superclass.subclasses.add(this);
+      superclass!.subclasses.add(this);
     }
   }
 
@@ -321,7 +318,7 @@
         }
       }
     }
-    return _kind;
+    return _kind!;
   }
 
   /// Returns `true` if this class has a `visitX` or `defaultX` method.
@@ -341,7 +338,6 @@
       case AstClassKind.utilityAsValue:
         return false;
     }
-    throw new UnsupportedError("Unexpected $kind");
   }
 
   /// Returns `true` if this class has a `visitXReference` or
@@ -362,13 +358,12 @@
       case AstClassKind.utilityAsValue:
         return false;
     }
-    throw new UnsupportedError("Unexpected $kind");
   }
 
   String dump([String indent = ""]) {
     StringBuffer sb = new StringBuffer();
     sb.writeln('${indent}${node.name} ($kind)');
-    for (AstField field in fields) {
+    for (AstField field in fields.values) {
       sb.write(field.dump('${indent}    '));
     }
     for (AstClass subclass in subclasses) {
@@ -463,11 +458,13 @@
 }
 
 class AstField {
+  final AstClass astClass;
   final Field node;
   final String name;
   final FieldType type;
+  final AstField? parentField;
 
-  AstField(this.node, this.name, this.type);
+  AstField(this.astClass, this.node, this.name, this.type, this.parentField);
 
   String dump([String indent = ""]) {
     StringBuffer sb = new StringBuffer();
@@ -515,15 +512,16 @@
     printDiagnosticMessage(message, print);
   };
 
-  InternalCompilerResult compilerResult = await kernelForProgramInternal(
+  InternalCompilerResult compilerResult = (await kernelForProgramInternal(
       astLibraryUri, options,
-      retainDataForTesting: true, requireMain: false);
-  ClassHierarchy classHierarchy = compilerResult.classHierarchy;
-  CoreTypes coreTypes = compilerResult.coreTypes;
+      retainDataForTesting: true,
+      requireMain: false)) as InternalCompilerResult;
+  ClassHierarchy classHierarchy = compilerResult.classHierarchy!;
+  CoreTypes coreTypes = compilerResult.coreTypes!;
   TypeEnvironment typeEnvironment =
       new TypeEnvironment(coreTypes, classHierarchy);
 
-  Library astLibrary = compilerResult.component.libraries
+  Library astLibrary = compilerResult.component!.libraries
       .singleWhere((library) => library.importUri == astLibraryUri);
 
   bool errorsFound = false;
@@ -532,12 +530,12 @@
     errorsFound = true;
   }
 
-  Map<String, String> declarativeClassesNames = {..._declarativeClassesNames};
+  Map<String, String?> declarativeClassesNames = {..._declarativeClassesNames};
   Set<String> classesWithoutVisitMethods = _classesWithoutVisitMethods.toSet();
   Set<String> classesWithoutVisitReference =
       _classesWithoutVisitReference.toSet();
-  Map<String, Map<String, FieldRule>> fieldRuleMap = {..._fieldRuleMap};
-  Map<String, FieldRule> nullFieldRules = {...?fieldRuleMap.remove(null)};
+  Map<String?, Map<String, FieldRule?>> fieldRuleMap = {..._fieldRuleMap};
+  Map<String, FieldRule?> nullFieldRules = {...?fieldRuleMap.remove(null)};
   Set<String> interchangeableClasses = _interchangeableClasses.toSet();
   for (Class cls in astLibrary.classes) {
     declarativeClassesNames.remove(cls.name);
@@ -545,16 +543,16 @@
     classesWithoutVisitReference.remove(cls.name);
     interchangeableClasses.remove(cls.name);
 
-    Map<String, FieldRule> fieldRules = {...?fieldRuleMap.remove(cls.name)};
+    Map<String, FieldRule?> fieldRules = {...?fieldRuleMap.remove(cls.name)};
     Set<String> renames = {};
-    Class parent = cls;
+    Class? parent = cls;
     while (parent != null && parent.enclosingLibrary == astLibrary) {
       for (Field field in parent.fields) {
         bool hasFieldRule = fieldRules.containsKey(field.name.text);
-        FieldRule fieldRule = fieldRules.remove(field.name.text);
+        FieldRule? fieldRule = fieldRules.remove(field.name.text);
         if (fieldRule != null) {
           if (fieldRule.name != null) {
-            renames.add(fieldRule.name);
+            renames.add(fieldRule.name!);
           }
         }
         if (!hasFieldRule) {
@@ -565,7 +563,7 @@
           }
         }
         if (nullFieldRules.containsKey(field.name.text)) {
-          FieldRule nullFieldRule = nullFieldRules.remove(field.name.text);
+          FieldRule? nullFieldRule = nullFieldRules.remove(field.name.text);
           if (nullFieldRule != null) {
             reportError('Only `null` is allowed for class `null`.');
           }
@@ -614,7 +612,7 @@
   Class classConstant =
       astLibrary.classes.singleWhere((cls) => cls.name == 'Constant');
 
-  Library canonicalNameLibrary = compilerResult.component.libraries
+  Library canonicalNameLibrary = compilerResult.component!.libraries
       .singleWhere((library) => library.importUri == canonicalNameLibraryUri);
 
   Class referenceClass = canonicalNameLibrary.classes
@@ -634,20 +632,20 @@
 
   /// Computes the [AstClass] corresponding to [node] if [node] is declared in
   /// 'package:kernel/ast.dart'.
-  AstClass computeAstClass(Class node) {
+  AstClass? computeAstClass(Class? node) {
     if (node == null) return null;
     if (node.enclosingLibrary != astLibrary) return null;
 
-    AstClass astClass = classMap[node];
+    AstClass? astClass = classMap[node];
     if (astClass == null) {
       bool isInterchangeable = _interchangeableClasses.contains(node.name);
       if (node == classNode) {
         astClass = new AstClass(node,
             kind: AstClassKind.root, isInterchangeable: isInterchangeable);
       } else if (classHierarchy.isSubtypeOf(node, classNode)) {
-        AstClass superclass = computeAstClass(node.superclass);
-        AstClassKind kind;
-        String declarativeName;
+        AstClass? superclass = computeAstClass(node.superclass);
+        AstClassKind? kind;
+        String? declarativeName;
         if (!node.isAbstract &&
             classHierarchy.isSubtypeOf(node, classNamedNode)) {
           kind = AstClassKind.named;
@@ -661,7 +659,7 @@
             declarativeName: declarativeName,
             isInterchangeable: isInterchangeable);
         for (Supertype supertype in node.implementedTypes) {
-          AstClass astSupertype = computeAstClass(supertype.classNode);
+          AstClass? astSupertype = computeAstClass(supertype.classNode);
           if (astSupertype != null) {
             astClass.interfaces.add(astSupertype);
             astSupertype.subtypes.add(astClass);
@@ -672,15 +670,13 @@
             kind: AstClassKind.utilityAsValue,
             isInterchangeable: isInterchangeable);
       } else {
-        AstClass superclass = computeAstClass(node.superclass);
+        AstClass? superclass = computeAstClass(node.superclass);
         astClass = new AstClass(node,
             superclass: superclass,
             kind: AstClassKind.utilityAsStructure,
             isInterchangeable: isInterchangeable);
       }
-      if (astClass != null) {
-        classMap[node] = astClass;
-      }
+      classMap[node] = astClass;
     }
     return astClass;
   }
@@ -689,12 +685,16 @@
     computeAstClass(cls);
   }
 
-  for (AstClass astClass in classMap.values) {
+  Set<AstClass> hasComputedFields = {};
+
+  void computeAstFields(AstClass astClass) {
+    if (!hasComputedFields.add(astClass)) return;
+
     void computeAstField(Field field, Substitution substitution) {
       if (field.isStatic) {
         return;
       }
-      FieldRule rule = getFieldRule(astClass, field);
+      FieldRule? rule = getFieldRule(astClass, field);
       if (rule == null) {
         return;
       }
@@ -702,7 +702,7 @@
 
       FieldType computeFieldType(DartType type) {
         bool isDeclarativeType = false;
-        for (InterfaceType declarativeType in declarativeTypes) {
+        for (DartType declarativeType in declarativeTypes) {
           if (type is InterfaceType &&
               typeEnvironment.isSubtypeOf(
                   type, declarativeType, SubtypeCheckMode.withNullabilities)) {
@@ -719,7 +719,7 @@
                 "and a rule must therefore specify "
                 "whether this constitutes declarative or referential use.");
           }
-          if (!rule.isDeclaration) {
+          if (!rule.isDeclaration!) {
             return new FieldType(type, AstFieldKind.use);
           }
         }
@@ -727,21 +727,21 @@
             typeEnvironment.isSubtypeOf(type, coreTypes.listNullableRawType,
                 SubtypeCheckMode.withNullabilities)) {
           DartType elementType = typeEnvironment
-              .getTypeArgumentsAsInstanceOf(type, coreTypes.listClass)
+              .getTypeArgumentsAsInstanceOf(type, coreTypes.listClass)!
               .single;
           return new ListFieldType(type, computeFieldType(elementType));
         } else if (type is InterfaceType &&
             typeEnvironment.isSubtypeOf(type, coreTypes.setNullableRawType,
                 SubtypeCheckMode.withNullabilities)) {
           DartType elementType = typeEnvironment
-              .getTypeArgumentsAsInstanceOf(type, coreTypes.setClass)
+              .getTypeArgumentsAsInstanceOf(type, coreTypes.setClass)!
               .single;
           return new SetFieldType(type, computeFieldType(elementType));
         } else if (type is InterfaceType &&
             typeEnvironment.isSubtypeOf(type, coreTypes.mapNullableRawType,
                 SubtypeCheckMode.withNullabilities)) {
           List<DartType> typeArguments = typeEnvironment
-              .getTypeArgumentsAsInstanceOf(type, coreTypes.mapClass);
+              .getTypeArgumentsAsInstanceOf(type, coreTypes.mapClass)!;
           return new MapFieldType(type, computeFieldType(typeArguments[0]),
               computeFieldType(typeArguments[1]));
         } else if (type is InterfaceType &&
@@ -754,7 +754,7 @@
           return new FieldType(type, AstFieldKind.reference);
         } else {
           if (type is InterfaceType) {
-            AstClass astClass = classMap[type.classNode];
+            AstClass? astClass = classMap[type.classNode];
             if (astClass != null &&
                 astClass.kind == AstClassKind.utilityAsStructure) {
               return new UtilityFieldType(type, astClass);
@@ -764,13 +764,13 @@
         }
       }
 
-      FieldType fieldType;
-      fieldType ??= computeFieldType(type);
-      astClass.fields
-          .add(new AstField(field, rule.name ?? field.name.text, fieldType));
+      FieldType? fieldType = computeFieldType(type);
+      String name = rule.name ?? field.name.text;
+      astClass.fields[name] = new AstField(
+          astClass, field, name, fieldType, astClass.superclass?.fields[name]);
     }
 
-    AstClass parent = astClass;
+    AstClass? parent = astClass;
     Substitution substitution = Substitution.empty;
     while (parent != null) {
       for (Field field in parent.node.fields) {
@@ -779,17 +779,21 @@
       parent = parent.superclass;
       if (parent != null) {
         substitution = Substitution.fromSupertype(
-            classHierarchy.getClassAsInstanceOf(astClass.node, parent.node));
+            classHierarchy.getClassAsInstanceOf(astClass.node, parent.node)!);
       }
     }
   }
 
-  AstClass astClassNode = classMap[classNode];
-  AstClass astClassNamedNode = classMap[classNamedNode];
-  AstClass astClassConstant = classMap[classConstant];
+  for (AstClass astClass in classMap.values) {
+    computeAstFields(astClass);
+  }
+
+  AstClass astClassNode = classMap[classNode]!;
+  AstClass astClassNamedNode = classMap[classNamedNode]!;
+  AstClass astClassConstant = classMap[classConstant]!;
 
   if (printDump) {
-    print(classMap[classNode].dump());
+    print(classMap[classNode]!.dump());
     for (AstClass astClass in classMap.values) {
       if (astClass != astClassNode && astClass.superclass == null) {
         print(astClass.dump());
diff --git a/pkg/front_end/tool/generate_ast_equivalence.dart b/pkg/front_end/tool/generate_ast_equivalence.dart
index 4d2aac6..83f689e 100644
--- a/pkg/front_end/tool/generate_ast_equivalence.dart
+++ b/pkg/front_end/tool/generate_ast_equivalence.dart
@@ -2,8 +2,6 @@
 // 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
-
 import 'dart:io';
 
 import 'ast_model.dart';
@@ -21,7 +19,7 @@
   new File.fromUri(output).writeAsStringSync(result);
 }
 
-Future<String> generateAstEquivalence(Uri repoDir, [AstModel astModel]) async {
+Future<String> generateAstEquivalence(Uri repoDir, [AstModel? astModel]) async {
   astModel ??= await deriveAstModel(repoDir);
   return generateVisitor(astModel, new EquivalenceVisitorStrategy());
 }
@@ -106,8 +104,8 @@
 
   String classCheckName(AstClass astClass) => 'check${astClass.name}';
 
-  String fieldCheckName(AstClass astClass, AstField field) =>
-      'check${astClass.name}_${field.name}';
+  String fieldCheckName(AstField field) =>
+      'check${field.astClass.name}_${field.name}';
 
   @override
   void handleDefaultVisit(
@@ -137,13 +135,13 @@
       case AstFieldKind.use:
         return '$prefix$shallowMatchDeclarations';
       case AstFieldKind.list:
-        ListFieldType listFieldType = fieldType;
+        ListFieldType listFieldType = fieldType as ListFieldType;
         String elementEquivalence =
             computeMatchingHelper(listFieldType.elementType);
         return '($thisName, $otherName) => $prefix$matchLists('
             '$thisName, $otherName, $elementEquivalence)';
       case AstFieldKind.set:
-        SetFieldType setFieldType = fieldType;
+        SetFieldType setFieldType = fieldType as SetFieldType;
         String elementMatching =
             computeMatchingHelper(setFieldType.elementType);
         String elementEquivalence =
@@ -151,7 +149,7 @@
         return '($thisName, $otherName) => $prefix$checkSets('
             '$thisName, $otherName, $elementMatching, $elementEquivalence)';
       case AstFieldKind.map:
-        MapFieldType mapFieldType = fieldType;
+        MapFieldType mapFieldType = fieldType as MapFieldType;
         String keyMatching = computeMatchingHelper(mapFieldType.keyType);
         String keyEquivalence = computeEquivalenceHelper(mapFieldType.keyType);
         String valueEquivalence =
@@ -161,7 +159,7 @@
             '$keyEquivalence, $valueEquivalence)';
       case AstFieldKind.utility:
         StringBuffer sb = new StringBuffer();
-        UtilityFieldType utilityFieldType = fieldType;
+        UtilityFieldType utilityFieldType = fieldType as UtilityFieldType;
         registerAstClassEquivalence(utilityFieldType.astClass);
         sb.writeln('''($thisName, $otherName, _) {
     if (identical($thisName, $otherName)) return true;
@@ -174,7 +172,6 @@
   }''');
         return sb.toString();
     }
-    throw ArgumentError("Unexpected field type ${fieldType}");
   }
 
   /// Computes the expression code for checking the equivalence of two fields
@@ -197,13 +194,13 @@
       case AstFieldKind.use:
         return '$prefix$checkDeclarations';
       case AstFieldKind.list:
-        ListFieldType listFieldType = fieldType;
+        ListFieldType listFieldType = fieldType as ListFieldType;
         String elementEquivalence =
             computeEquivalenceHelper(listFieldType.elementType);
         return '($thisName, $otherName) => $prefix$checkLists('
             '$thisName, $otherName, $elementEquivalence)';
       case AstFieldKind.set:
-        SetFieldType setFieldType = fieldType;
+        SetFieldType setFieldType = fieldType as SetFieldType;
         String elementMatching =
             computeMatchingHelper(setFieldType.elementType);
         String elementEquivalence =
@@ -211,7 +208,7 @@
         return '($thisName, $otherName) => $prefix$checkSets('
             '$thisName, $otherName, $elementMatching, $elementEquivalence)';
       case AstFieldKind.map:
-        MapFieldType mapFieldType = fieldType;
+        MapFieldType mapFieldType = fieldType as MapFieldType;
         String keyMatching = computeMatchingHelper(mapFieldType.keyType);
         String keyEquivalence = computeEquivalenceHelper(mapFieldType.keyType);
         String valueEquivalence =
@@ -221,7 +218,7 @@
             '$keyEquivalence, $valueEquivalence)';
       case AstFieldKind.utility:
         StringBuffer sb = new StringBuffer();
-        UtilityFieldType utilityFieldType = fieldType;
+        UtilityFieldType utilityFieldType = fieldType as UtilityFieldType;
         registerAstClassEquivalence(utilityFieldType.astClass);
         sb.writeln('''($thisName, $otherName, _) {
     if (identical($thisName, $otherName)) return true;
@@ -234,7 +231,6 @@
   }''');
         return sb.toString();
     }
-    throw ArgumentError("Unexpected field type ${fieldType}");
   }
 
   /// Registers that a strategy method is needed for checking [astClass].
@@ -275,10 +271,10 @@
     }
     classStrategy.writeln('''
     bool result = true;''');
-    for (AstField field in astClass.fields) {
-      registerAstFieldEquivalence(astClass, field);
+    for (AstField field in astClass.fields.values) {
+      registerAstFieldEquivalence(field);
       classStrategy.writeln('''
-    if (!${fieldCheckName(astClass, field)}(visitor, $thisName, $otherName)) {
+    if (!${fieldCheckName(field)}(visitor, $thisName, $otherName)) {
       result = visitor.$resultOnInequivalence;
     }''');
     }
@@ -300,69 +296,75 @@
   ///
   /// If the method has not already been generated, it is generated and stored
   /// in [_fieldStrategyMembers].
-  void registerAstFieldEquivalence(AstClass astClass, AstField field) {
+  void registerAstFieldEquivalence(AstField field) {
     if (_fieldStrategyMembers.containsKey(field)) return;
 
+    AstClass astClass = field.astClass;
     String thisName = 'node';
     String otherName = 'other';
     StringBuffer fieldStrategy = new StringBuffer();
     fieldStrategy.writeln('''
-  bool ${fieldCheckName(astClass, field)}(
+  bool ${fieldCheckName(field)}(
       $visitorName visitor,
       ${astClass.name} $thisName,
       ${astClass.name} $otherName) {''');
-
-    switch (field.type.kind) {
-      case AstFieldKind.value:
-        fieldStrategy.writeln('''
+    if (field.parentField != null) {
+      registerAstFieldEquivalence(field.parentField!);
+      fieldStrategy.writeln('''
+    return ${fieldCheckName(field.parentField!)}(
+        visitor, $thisName, $otherName);''');
+    } else {
+      switch (field.type.kind) {
+        case AstFieldKind.value:
+          fieldStrategy.writeln('''
     return visitor.$checkValues(
         $thisName.${field.name},
         $otherName.${field.name},
         '${field.name}');''');
-        break;
-      case AstFieldKind.node:
-        fieldStrategy.writeln('''
+          break;
+        case AstFieldKind.node:
+          fieldStrategy.writeln('''
     return visitor.$checkNodes(
         $thisName.${field.name},
         $otherName.${field.name},
         '${field.name}');''');
-        break;
-      case AstFieldKind.reference:
-        fieldStrategy.writeln('''
+          break;
+        case AstFieldKind.reference:
+          fieldStrategy.writeln('''
     return visitor.$checkReferences(
         $thisName.${field.name},
         $otherName.${field.name},
         '${field.name}');''');
-        break;
-      case AstFieldKind.use:
-        fieldStrategy.writeln('''
+          break;
+        case AstFieldKind.use:
+          fieldStrategy.writeln('''
     return visitor.$checkDeclarations(
         $thisName.${field.name},
         $otherName.${field.name},
         '${field.name}');''');
-        break;
-      case AstFieldKind.list:
-        ListFieldType listFieldType = field.type;
-        fieldStrategy.writeln('''
+          break;
+        case AstFieldKind.list:
+          ListFieldType listFieldType = field.type as ListFieldType;
+          fieldStrategy.writeln('''
     return visitor.$checkLists(
         $thisName.${field.name},
         $otherName.${field.name},
         ${computeEquivalenceHelper(listFieldType.elementType, 'visitor.')},
         '${field.name}');''');
-        break;
-      case AstFieldKind.set:
-        SetFieldType setFieldType = field.type;
-        fieldStrategy.writeln('''
+          break;
+        case AstFieldKind.set:
+          SetFieldType setFieldType = field.type as SetFieldType;
+          fieldStrategy.writeln('''
     return visitor.$checkSets(
         $thisName.${field.name},
         $otherName.${field.name},
         ${computeMatchingHelper(setFieldType.elementType, 'visitor.')},
         ${computeEquivalenceHelper(setFieldType.elementType, 'visitor.')},
         '${field.name}');''');
-        break;
-      case AstFieldKind.map:
-        MapFieldType mapFieldType = field.type;
-        fieldStrategy.writeln('''
+          break;
+        case AstFieldKind.map:
+          MapFieldType mapFieldType = field.type as MapFieldType;
+          fieldStrategy.writeln('''
     return visitor.$checkMaps(
         $thisName.${field.name},
         $otherName.${field.name},
@@ -370,17 +372,18 @@
         ${computeEquivalenceHelper(mapFieldType.keyType, 'visitor.')},
         ${computeEquivalenceHelper(mapFieldType.valueType, 'visitor.')},
         '${field.name}');''');
-        break;
-      case AstFieldKind.utility:
-        UtilityFieldType utilityFieldType = field.type;
-        registerAstClassEquivalence(utilityFieldType.astClass);
-        fieldStrategy.writeln('''
+          break;
+        case AstFieldKind.utility:
+          UtilityFieldType utilityFieldType = field.type as UtilityFieldType;
+          registerAstClassEquivalence(utilityFieldType.astClass);
+          fieldStrategy.writeln('''
     '${field.name}';
     return ${classCheckName(utilityFieldType.astClass)}(
         visitor,
         $thisName.${field.name},
         $otherName.${field.name});''');
-        break;
+          break;
+      }
     }
     fieldStrategy.writeln('''
   }''');
diff --git a/pkg/front_end/tool/visitor_generator.dart b/pkg/front_end/tool/visitor_generator.dart
index a965151..d4befb5 100644
--- a/pkg/front_end/tool/visitor_generator.dart
+++ b/pkg/front_end/tool/visitor_generator.dart
@@ -2,8 +2,6 @@
 // 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
-
 import 'package:dart_style/dart_style.dart' show DartFormatter;
 
 import 'ast_model.dart';
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index c65b3a2..4cc9711 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -860,6 +860,7 @@
         function: super.clone(node.function),
         fileUri: node.fileUri,
         reference: reference)
+      ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..annotations = cloneAnnotations && !node.annotations.isEmpty
           ? node.annotations.map(super.clone).toList()
           : const <Expression>[];
diff --git a/pkg/kernel/lib/src/equivalence.dart b/pkg/kernel/lib/src/equivalence.dart
index 9034fe6..2f9fab4 100644
--- a/pkg/kernel/lib/src/equivalence.dart
+++ b/pkg/kernel/lib/src/equivalence.dart
@@ -4529,15 +4529,30 @@
         node.fields, other.fields, visitor.checkNodes, 'fields');
   }
 
-  bool checkLibrary_reference(
-      EquivalenceVisitor visitor, Library node, Library other) {
+  bool checkNamedNode_reference(
+      EquivalenceVisitor visitor, NamedNode node, NamedNode other) {
     return visitor.checkReferences(
         node.reference, other.reference, 'reference');
   }
 
+  bool checkLibrary_reference(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return checkNamedNode_reference(visitor, node, other);
+  }
+
+  bool checkTreeNode_fileOffset(
+      EquivalenceVisitor visitor, TreeNode node, TreeNode other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkNamedNode_fileOffset(
+      EquivalenceVisitor visitor, NamedNode node, NamedNode other) {
+    return checkTreeNode_fileOffset(visitor, node, other);
+  }
+
   bool checkLibrary_fileOffset(
       EquivalenceVisitor visitor, Library node, Library other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkNamedNode_fileOffset(visitor, node, other);
   }
 
   bool checkTypedef_fileUri(
@@ -4593,13 +4608,12 @@
 
   bool checkTypedef_reference(
       EquivalenceVisitor visitor, Typedef node, Typedef other) {
-    return visitor.checkReferences(
-        node.reference, other.reference, 'reference');
+    return checkNamedNode_reference(visitor, node, other);
   }
 
   bool checkTypedef_fileOffset(
       EquivalenceVisitor visitor, Typedef node, Typedef other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkNamedNode_fileOffset(visitor, node, other);
   }
 
   bool checkClass_startFileOffset(
@@ -4680,13 +4694,12 @@
 
   bool checkClass_reference(
       EquivalenceVisitor visitor, Class node, Class other) {
-    return visitor.checkReferences(
-        node.reference, other.reference, 'reference');
+    return checkNamedNode_reference(visitor, node, other);
   }
 
   bool checkClass_fileOffset(
       EquivalenceVisitor visitor, Class node, Class other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkNamedNode_fileOffset(visitor, node, other);
   }
 
   bool checkExtension_name(
@@ -4753,13 +4766,12 @@
 
   bool checkExtension_reference(
       EquivalenceVisitor visitor, Extension node, Extension other) {
-    return visitor.checkReferences(
-        node.reference, other.reference, 'reference');
+    return checkNamedNode_reference(visitor, node, other);
   }
 
   bool checkExtension_fileOffset(
       EquivalenceVisitor visitor, Extension node, Extension other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkNamedNode_fileOffset(visitor, node, other);
   }
 
   bool checkField_type(EquivalenceVisitor visitor, Field node, Field other) {
@@ -4782,30 +4794,54 @@
         node.setterReference, other.setterReference, 'setterReference');
   }
 
-  bool checkField_fileEndOffset(
-      EquivalenceVisitor visitor, Field node, Field other) {
+  bool checkMember_fileEndOffset(
+      EquivalenceVisitor visitor, Member node, Member other) {
     return visitor.checkValues(
         node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
   }
 
-  bool checkField_annotations(
+  bool checkField_fileEndOffset(
       EquivalenceVisitor visitor, Field node, Field other) {
+    return checkMember_fileEndOffset(visitor, node, other);
+  }
+
+  bool checkMember_annotations(
+      EquivalenceVisitor visitor, Member node, Member other) {
     return visitor.checkLists(
         node.annotations, other.annotations, visitor.checkNodes, 'annotations');
   }
 
-  bool checkField_name(EquivalenceVisitor visitor, Field node, Field other) {
+  bool checkField_annotations(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return checkMember_annotations(visitor, node, other);
+  }
+
+  bool checkMember_name(EquivalenceVisitor visitor, Member node, Member other) {
     return visitor.checkNodes(node.name, other.name, 'name');
   }
 
-  bool checkField_fileUri(EquivalenceVisitor visitor, Field node, Field other) {
+  bool checkField_name(EquivalenceVisitor visitor, Field node, Field other) {
+    return checkMember_name(visitor, node, other);
+  }
+
+  bool checkMember_fileUri(
+      EquivalenceVisitor visitor, Member node, Member other) {
     return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
   }
 
+  bool checkField_fileUri(EquivalenceVisitor visitor, Field node, Field other) {
+    return checkMember_fileUri(visitor, node, other);
+  }
+
+  bool checkMember_transformerFlags(
+      EquivalenceVisitor visitor, Member node, Member other) {
+    return visitor.checkValues(
+        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+  }
+
   bool checkField_transformerFlags(
       EquivalenceVisitor visitor, Field node, Field other) {
-    return visitor.checkValues(
-        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+    return checkMember_transformerFlags(visitor, node, other);
   }
 
   bool checkField_getterReference(
@@ -4814,9 +4850,14 @@
         node.getterReference, other.getterReference, 'getterReference');
   }
 
+  bool checkMember_fileOffset(
+      EquivalenceVisitor visitor, Member node, Member other) {
+    return checkNamedNode_fileOffset(visitor, node, other);
+  }
+
   bool checkField_fileOffset(
       EquivalenceVisitor visitor, Field node, Field other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkMember_fileOffset(visitor, node, other);
   }
 
   bool checkConstructor_startFileOffset(
@@ -4843,41 +4884,42 @@
 
   bool checkConstructor_fileEndOffset(
       EquivalenceVisitor visitor, Constructor node, Constructor other) {
-    return visitor.checkValues(
-        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+    return checkMember_fileEndOffset(visitor, node, other);
   }
 
   bool checkConstructor_annotations(
       EquivalenceVisitor visitor, Constructor node, Constructor other) {
-    return visitor.checkLists(
-        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+    return checkMember_annotations(visitor, node, other);
   }
 
   bool checkConstructor_name(
       EquivalenceVisitor visitor, Constructor node, Constructor other) {
-    return visitor.checkNodes(node.name, other.name, 'name');
+    return checkMember_name(visitor, node, other);
   }
 
   bool checkConstructor_fileUri(
       EquivalenceVisitor visitor, Constructor node, Constructor other) {
-    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+    return checkMember_fileUri(visitor, node, other);
   }
 
   bool checkConstructor_transformerFlags(
       EquivalenceVisitor visitor, Constructor node, Constructor other) {
-    return visitor.checkValues(
-        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+    return checkMember_transformerFlags(visitor, node, other);
+  }
+
+  bool checkMember_reference(
+      EquivalenceVisitor visitor, Member node, Member other) {
+    return checkNamedNode_reference(visitor, node, other);
   }
 
   bool checkConstructor_reference(
       EquivalenceVisitor visitor, Constructor node, Constructor other) {
-    return visitor.checkReferences(
-        node.reference, other.reference, 'reference');
+    return checkMember_reference(visitor, node, other);
   }
 
   bool checkConstructor_fileOffset(
       EquivalenceVisitor visitor, Constructor node, Constructor other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkMember_fileOffset(visitor, node, other);
   }
 
   bool checkRedirectingFactory_flags(EquivalenceVisitor visitor,
@@ -4904,41 +4946,37 @@
 
   bool checkRedirectingFactory_fileEndOffset(EquivalenceVisitor visitor,
       RedirectingFactory node, RedirectingFactory other) {
-    return visitor.checkValues(
-        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+    return checkMember_fileEndOffset(visitor, node, other);
   }
 
   bool checkRedirectingFactory_annotations(EquivalenceVisitor visitor,
       RedirectingFactory node, RedirectingFactory other) {
-    return visitor.checkLists(
-        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+    return checkMember_annotations(visitor, node, other);
   }
 
   bool checkRedirectingFactory_name(EquivalenceVisitor visitor,
       RedirectingFactory node, RedirectingFactory other) {
-    return visitor.checkNodes(node.name, other.name, 'name');
+    return checkMember_name(visitor, node, other);
   }
 
   bool checkRedirectingFactory_fileUri(EquivalenceVisitor visitor,
       RedirectingFactory node, RedirectingFactory other) {
-    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+    return checkMember_fileUri(visitor, node, other);
   }
 
   bool checkRedirectingFactory_transformerFlags(EquivalenceVisitor visitor,
       RedirectingFactory node, RedirectingFactory other) {
-    return visitor.checkValues(
-        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+    return checkMember_transformerFlags(visitor, node, other);
   }
 
   bool checkRedirectingFactory_reference(EquivalenceVisitor visitor,
       RedirectingFactory node, RedirectingFactory other) {
-    return visitor.checkReferences(
-        node.reference, other.reference, 'reference');
+    return checkMember_reference(visitor, node, other);
   }
 
   bool checkRedirectingFactory_fileOffset(EquivalenceVisitor visitor,
       RedirectingFactory node, RedirectingFactory other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkMember_fileOffset(visitor, node, other);
   }
 
   bool checkProcedure_startFileOffset(
@@ -4975,41 +5013,37 @@
 
   bool checkProcedure_fileEndOffset(
       EquivalenceVisitor visitor, Procedure node, Procedure other) {
-    return visitor.checkValues(
-        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+    return checkMember_fileEndOffset(visitor, node, other);
   }
 
   bool checkProcedure_annotations(
       EquivalenceVisitor visitor, Procedure node, Procedure other) {
-    return visitor.checkLists(
-        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+    return checkMember_annotations(visitor, node, other);
   }
 
   bool checkProcedure_name(
       EquivalenceVisitor visitor, Procedure node, Procedure other) {
-    return visitor.checkNodes(node.name, other.name, 'name');
+    return checkMember_name(visitor, node, other);
   }
 
   bool checkProcedure_fileUri(
       EquivalenceVisitor visitor, Procedure node, Procedure other) {
-    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+    return checkMember_fileUri(visitor, node, other);
   }
 
   bool checkProcedure_transformerFlags(
       EquivalenceVisitor visitor, Procedure node, Procedure other) {
-    return visitor.checkValues(
-        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+    return checkMember_transformerFlags(visitor, node, other);
   }
 
   bool checkProcedure_reference(
       EquivalenceVisitor visitor, Procedure node, Procedure other) {
-    return visitor.checkReferences(
-        node.reference, other.reference, 'reference');
+    return checkMember_reference(visitor, node, other);
   }
 
   bool checkProcedure_fileOffset(
       EquivalenceVisitor visitor, Procedure node, Procedure other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkMember_fileOffset(visitor, node, other);
   }
 
   bool checkLibraryDependency_flags(EquivalenceVisitor visitor,
@@ -5044,7 +5078,7 @@
 
   bool checkLibraryDependency_fileOffset(EquivalenceVisitor visitor,
       LibraryDependency node, LibraryDependency other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkLibraryPart_annotations(
@@ -5060,7 +5094,7 @@
 
   bool checkLibraryPart_fileOffset(
       EquivalenceVisitor visitor, LibraryPart node, LibraryPart other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkCombinator_isShow(
@@ -5076,18 +5110,28 @@
 
   bool checkCombinator_fileOffset(
       EquivalenceVisitor visitor, Combinator node, Combinator other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
-  bool checkInvalidInitializer_isSynthetic(EquivalenceVisitor visitor,
-      InvalidInitializer node, InvalidInitializer other) {
+  bool checkInitializer_isSynthetic(
+      EquivalenceVisitor visitor, Initializer node, Initializer other) {
     return visitor.checkValues(
         node.isSynthetic, other.isSynthetic, 'isSynthetic');
   }
 
+  bool checkInvalidInitializer_isSynthetic(EquivalenceVisitor visitor,
+      InvalidInitializer node, InvalidInitializer other) {
+    return checkInitializer_isSynthetic(visitor, node, other);
+  }
+
+  bool checkInitializer_fileOffset(
+      EquivalenceVisitor visitor, Initializer node, Initializer other) {
+    return checkTreeNode_fileOffset(visitor, node, other);
+  }
+
   bool checkInvalidInitializer_fileOffset(EquivalenceVisitor visitor,
       InvalidInitializer node, InvalidInitializer other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInitializer_fileOffset(visitor, node, other);
   }
 
   bool checkFieldInitializer_fieldReference(EquivalenceVisitor visitor,
@@ -5103,13 +5147,12 @@
 
   bool checkFieldInitializer_isSynthetic(EquivalenceVisitor visitor,
       FieldInitializer node, FieldInitializer other) {
-    return visitor.checkValues(
-        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+    return checkInitializer_isSynthetic(visitor, node, other);
   }
 
   bool checkFieldInitializer_fileOffset(EquivalenceVisitor visitor,
       FieldInitializer node, FieldInitializer other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInitializer_fileOffset(visitor, node, other);
   }
 
   bool checkSuperInitializer_targetReference(EquivalenceVisitor visitor,
@@ -5125,13 +5168,12 @@
 
   bool checkSuperInitializer_isSynthetic(EquivalenceVisitor visitor,
       SuperInitializer node, SuperInitializer other) {
-    return visitor.checkValues(
-        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+    return checkInitializer_isSynthetic(visitor, node, other);
   }
 
   bool checkSuperInitializer_fileOffset(EquivalenceVisitor visitor,
       SuperInitializer node, SuperInitializer other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInitializer_fileOffset(visitor, node, other);
   }
 
   bool checkRedirectingInitializer_targetReference(EquivalenceVisitor visitor,
@@ -5147,13 +5189,12 @@
 
   bool checkRedirectingInitializer_isSynthetic(EquivalenceVisitor visitor,
       RedirectingInitializer node, RedirectingInitializer other) {
-    return visitor.checkValues(
-        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+    return checkInitializer_isSynthetic(visitor, node, other);
   }
 
   bool checkRedirectingInitializer_fileOffset(EquivalenceVisitor visitor,
       RedirectingInitializer node, RedirectingInitializer other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInitializer_fileOffset(visitor, node, other);
   }
 
   bool checkLocalInitializer_variable(EquivalenceVisitor visitor,
@@ -5163,13 +5204,12 @@
 
   bool checkLocalInitializer_isSynthetic(EquivalenceVisitor visitor,
       LocalInitializer node, LocalInitializer other) {
-    return visitor.checkValues(
-        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+    return checkInitializer_isSynthetic(visitor, node, other);
   }
 
   bool checkLocalInitializer_fileOffset(EquivalenceVisitor visitor,
       LocalInitializer node, LocalInitializer other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInitializer_fileOffset(visitor, node, other);
   }
 
   bool checkAssertInitializer_statement(EquivalenceVisitor visitor,
@@ -5179,13 +5219,12 @@
 
   bool checkAssertInitializer_isSynthetic(EquivalenceVisitor visitor,
       AssertInitializer node, AssertInitializer other) {
-    return visitor.checkValues(
-        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+    return checkInitializer_isSynthetic(visitor, node, other);
   }
 
   bool checkAssertInitializer_fileOffset(EquivalenceVisitor visitor,
       AssertInitializer node, AssertInitializer other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInitializer_fileOffset(visitor, node, other);
   }
 
   bool checkFunctionNode_fileEndOffset(
@@ -5254,7 +5293,7 @@
 
   bool checkFunctionNode_fileOffset(
       EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkInvalidExpression_message(EquivalenceVisitor visitor,
@@ -5267,9 +5306,14 @@
     return visitor.checkNodes(node.expression, other.expression, 'expression');
   }
 
+  bool checkExpression_fileOffset(
+      EquivalenceVisitor visitor, Expression node, Expression other) {
+    return checkTreeNode_fileOffset(visitor, node, other);
+  }
+
   bool checkInvalidExpression_fileOffset(EquivalenceVisitor visitor,
       InvalidExpression node, InvalidExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkVariableGet_variable(
@@ -5285,7 +5329,7 @@
 
   bool checkVariableGet_fileOffset(
       EquivalenceVisitor visitor, VariableGet node, VariableGet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkVariableSet_variable(
@@ -5300,7 +5344,7 @@
 
   bool checkVariableSet_fileOffset(
       EquivalenceVisitor visitor, VariableSet node, VariableSet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkDynamicGet_kind(
@@ -5320,7 +5364,7 @@
 
   bool checkDynamicGet_fileOffset(
       EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkInstanceGet_kind(
@@ -5351,7 +5395,7 @@
 
   bool checkInstanceGet_fileOffset(
       EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkFunctionTearOff_receiver(
@@ -5361,7 +5405,7 @@
 
   bool checkFunctionTearOff_fileOffset(
       EquivalenceVisitor visitor, FunctionTearOff node, FunctionTearOff other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkInstanceTearOff_kind(
@@ -5392,7 +5436,7 @@
 
   bool checkInstanceTearOff_fileOffset(
       EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkDynamicSet_kind(
@@ -5417,7 +5461,7 @@
 
   bool checkDynamicSet_fileOffset(
       EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkInstanceSet_kind(
@@ -5448,7 +5492,7 @@
 
   bool checkInstanceSet_fileOffset(
       EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkSuperPropertyGet_name(EquivalenceVisitor visitor,
@@ -5466,7 +5510,7 @@
 
   bool checkSuperPropertyGet_fileOffset(EquivalenceVisitor visitor,
       SuperPropertyGet node, SuperPropertyGet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkSuperPropertySet_name(EquivalenceVisitor visitor,
@@ -5489,7 +5533,7 @@
 
   bool checkSuperPropertySet_fileOffset(EquivalenceVisitor visitor,
       SuperPropertySet node, SuperPropertySet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkStaticGet_targetReference(
@@ -5500,7 +5544,7 @@
 
   bool checkStaticGet_fileOffset(
       EquivalenceVisitor visitor, StaticGet node, StaticGet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkStaticTearOff_targetReference(
@@ -5511,7 +5555,7 @@
 
   bool checkStaticTearOff_fileOffset(
       EquivalenceVisitor visitor, StaticTearOff node, StaticTearOff other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkStaticSet_targetReference(
@@ -5527,7 +5571,7 @@
 
   bool checkStaticSet_fileOffset(
       EquivalenceVisitor visitor, StaticSet node, StaticSet other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkDynamicInvocation_kind(EquivalenceVisitor visitor,
@@ -5550,9 +5594,19 @@
     return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
   }
 
+  bool checkInvocationExpression_fileOffset(EquivalenceVisitor visitor,
+      InvocationExpression node, InvocationExpression other) {
+    return checkExpression_fileOffset(visitor, node, other);
+  }
+
+  bool checkInstanceInvocationExpression_fileOffset(EquivalenceVisitor visitor,
+      InstanceInvocationExpression node, InstanceInvocationExpression other) {
+    return checkInvocationExpression_fileOffset(visitor, node, other);
+  }
+
   bool checkDynamicInvocation_fileOffset(EquivalenceVisitor visitor,
       DynamicInvocation node, DynamicInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInstanceInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkInstanceInvocation_kind(EquivalenceVisitor visitor,
@@ -5596,7 +5650,7 @@
 
   bool checkInstanceInvocation_fileOffset(EquivalenceVisitor visitor,
       InstanceInvocation node, InstanceInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInstanceInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkInstanceGetterInvocation_kind(EquivalenceVisitor visitor,
@@ -5640,7 +5694,7 @@
 
   bool checkInstanceGetterInvocation_fileOffset(EquivalenceVisitor visitor,
       InstanceGetterInvocation node, InstanceGetterInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInstanceInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkFunctionInvocation_kind(EquivalenceVisitor visitor,
@@ -5666,7 +5720,7 @@
 
   bool checkFunctionInvocation_fileOffset(EquivalenceVisitor visitor,
       FunctionInvocation node, FunctionInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInstanceInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkLocalFunctionInvocation_variable(EquivalenceVisitor visitor,
@@ -5687,7 +5741,7 @@
 
   bool checkLocalFunctionInvocation_fileOffset(EquivalenceVisitor visitor,
       LocalFunctionInvocation node, LocalFunctionInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkSuperMethodInvocation_name(EquivalenceVisitor visitor,
@@ -5710,7 +5764,7 @@
 
   bool checkSuperMethodInvocation_fileOffset(EquivalenceVisitor visitor,
       SuperMethodInvocation node, SuperMethodInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkStaticInvocation_targetReference(EquivalenceVisitor visitor,
@@ -5731,7 +5785,7 @@
 
   bool checkStaticInvocation_fileOffset(EquivalenceVisitor visitor,
       StaticInvocation node, StaticInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkConstructorInvocation_targetReference(EquivalenceVisitor visitor,
@@ -5752,7 +5806,7 @@
 
   bool checkConstructorInvocation_fileOffset(EquivalenceVisitor visitor,
       ConstructorInvocation node, ConstructorInvocation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkInvocationExpression_fileOffset(visitor, node, other);
   }
 
   bool checkEqualsNull_expression(
@@ -5762,7 +5816,7 @@
 
   bool checkEqualsNull_fileOffset(
       EquivalenceVisitor visitor, EqualsNull node, EqualsNull other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkEqualsCall_left(
@@ -5789,7 +5843,7 @@
 
   bool checkEqualsCall_fileOffset(
       EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkInstantiation_expression(
@@ -5805,7 +5859,7 @@
 
   bool checkInstantiation_fileOffset(
       EquivalenceVisitor visitor, Instantiation node, Instantiation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkNot_operand(EquivalenceVisitor visitor, Not node, Not other) {
@@ -5813,7 +5867,7 @@
   }
 
   bool checkNot_fileOffset(EquivalenceVisitor visitor, Not node, Not other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkLogicalExpression_left(EquivalenceVisitor visitor,
@@ -5834,7 +5888,7 @@
 
   bool checkLogicalExpression_fileOffset(EquivalenceVisitor visitor,
       LogicalExpression node, LogicalExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkConditionalExpression_condition(EquivalenceVisitor visitor,
@@ -5859,7 +5913,7 @@
 
   bool checkConditionalExpression_fileOffset(EquivalenceVisitor visitor,
       ConditionalExpression node, ConditionalExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkStringConcatenation_expressions(EquivalenceVisitor visitor,
@@ -5870,7 +5924,7 @@
 
   bool checkStringConcatenation_fileOffset(EquivalenceVisitor visitor,
       StringConcatenation node, StringConcatenation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkListConcatenation_typeArgument(EquivalenceVisitor visitor,
@@ -5887,7 +5941,7 @@
 
   bool checkListConcatenation_fileOffset(EquivalenceVisitor visitor,
       ListConcatenation node, ListConcatenation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkSetConcatenation_typeArgument(EquivalenceVisitor visitor,
@@ -5904,7 +5958,7 @@
 
   bool checkSetConcatenation_fileOffset(EquivalenceVisitor visitor,
       SetConcatenation node, SetConcatenation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkMapConcatenation_keyType(EquivalenceVisitor visitor,
@@ -5925,7 +5979,7 @@
 
   bool checkMapConcatenation_fileOffset(EquivalenceVisitor visitor,
       MapConcatenation node, MapConcatenation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkInstanceCreation_classReference(EquivalenceVisitor visitor,
@@ -5965,7 +6019,7 @@
 
   bool checkInstanceCreation_fileOffset(EquivalenceVisitor visitor,
       InstanceCreation node, InstanceCreation other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkFileUriExpression_fileUri(EquivalenceVisitor visitor,
@@ -5980,7 +6034,7 @@
 
   bool checkFileUriExpression_fileOffset(EquivalenceVisitor visitor,
       FileUriExpression node, FileUriExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkIsExpression_flags(
@@ -6000,7 +6054,7 @@
 
   bool checkIsExpression_fileOffset(
       EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkAsExpression_flags(
@@ -6020,7 +6074,7 @@
 
   bool checkAsExpression_fileOffset(
       EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkNullCheck_operand(
@@ -6030,7 +6084,7 @@
 
   bool checkNullCheck_fileOffset(
       EquivalenceVisitor visitor, NullCheck node, NullCheck other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkStringLiteral_value(
@@ -6038,9 +6092,14 @@
     return visitor.checkValues(node.value, other.value, 'value');
   }
 
+  bool checkBasicLiteral_fileOffset(
+      EquivalenceVisitor visitor, BasicLiteral node, BasicLiteral other) {
+    return checkExpression_fileOffset(visitor, node, other);
+  }
+
   bool checkStringLiteral_fileOffset(
       EquivalenceVisitor visitor, StringLiteral node, StringLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkBasicLiteral_fileOffset(visitor, node, other);
   }
 
   bool checkIntLiteral_value(
@@ -6050,7 +6109,7 @@
 
   bool checkIntLiteral_fileOffset(
       EquivalenceVisitor visitor, IntLiteral node, IntLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkBasicLiteral_fileOffset(visitor, node, other);
   }
 
   bool checkDoubleLiteral_value(
@@ -6060,7 +6119,7 @@
 
   bool checkDoubleLiteral_fileOffset(
       EquivalenceVisitor visitor, DoubleLiteral node, DoubleLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkBasicLiteral_fileOffset(visitor, node, other);
   }
 
   bool checkBoolLiteral_value(
@@ -6070,12 +6129,12 @@
 
   bool checkBoolLiteral_fileOffset(
       EquivalenceVisitor visitor, BoolLiteral node, BoolLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkBasicLiteral_fileOffset(visitor, node, other);
   }
 
   bool checkNullLiteral_fileOffset(
       EquivalenceVisitor visitor, NullLiteral node, NullLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkBasicLiteral_fileOffset(visitor, node, other);
   }
 
   bool checkSymbolLiteral_value(
@@ -6085,7 +6144,7 @@
 
   bool checkSymbolLiteral_fileOffset(
       EquivalenceVisitor visitor, SymbolLiteral node, SymbolLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkTypeLiteral_type(
@@ -6095,17 +6154,17 @@
 
   bool checkTypeLiteral_fileOffset(
       EquivalenceVisitor visitor, TypeLiteral node, TypeLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkThisExpression_fileOffset(
       EquivalenceVisitor visitor, ThisExpression node, ThisExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkRethrow_fileOffset(
       EquivalenceVisitor visitor, Rethrow node, Rethrow other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkThrow_expression(
@@ -6115,7 +6174,7 @@
 
   bool checkThrow_fileOffset(
       EquivalenceVisitor visitor, Throw node, Throw other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkListLiteral_isConst(
@@ -6137,7 +6196,7 @@
 
   bool checkListLiteral_fileOffset(
       EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkSetLiteral_isConst(
@@ -6159,7 +6218,7 @@
 
   bool checkSetLiteral_fileOffset(
       EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkMapLiteral_isConst(
@@ -6185,7 +6244,7 @@
 
   bool checkMapLiteral_fileOffset(
       EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkAwaitExpression_operand(
@@ -6195,7 +6254,7 @@
 
   bool checkAwaitExpression_fileOffset(
       EquivalenceVisitor visitor, AwaitExpression node, AwaitExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkFunctionExpression_function(EquivalenceVisitor visitor,
@@ -6205,7 +6264,7 @@
 
   bool checkFunctionExpression_fileOffset(EquivalenceVisitor visitor,
       FunctionExpression node, FunctionExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkConstantExpression_constant(EquivalenceVisitor visitor,
@@ -6220,7 +6279,7 @@
 
   bool checkConstantExpression_fileOffset(EquivalenceVisitor visitor,
       ConstantExpression node, ConstantExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkLet_variable(EquivalenceVisitor visitor, Let node, Let other) {
@@ -6232,7 +6291,7 @@
   }
 
   bool checkLet_fileOffset(EquivalenceVisitor visitor, Let node, Let other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkBlockExpression_body(
@@ -6247,7 +6306,7 @@
 
   bool checkBlockExpression_fileOffset(
       EquivalenceVisitor visitor, BlockExpression node, BlockExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkLoadLibrary_import(
@@ -6257,7 +6316,7 @@
 
   bool checkLoadLibrary_fileOffset(
       EquivalenceVisitor visitor, LoadLibrary node, LoadLibrary other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkCheckLibraryIsLoaded_import(EquivalenceVisitor visitor,
@@ -6267,7 +6326,7 @@
 
   bool checkCheckLibraryIsLoaded_fileOffset(EquivalenceVisitor visitor,
       CheckLibraryIsLoaded node, CheckLibraryIsLoaded other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkConstructorTearOff_targetReference(EquivalenceVisitor visitor,
@@ -6278,7 +6337,7 @@
 
   bool checkConstructorTearOff_fileOffset(EquivalenceVisitor visitor,
       ConstructorTearOff node, ConstructorTearOff other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkRedirectingFactoryTearOff_targetReference(
@@ -6291,7 +6350,7 @@
 
   bool checkRedirectingFactoryTearOff_fileOffset(EquivalenceVisitor visitor,
       RedirectingFactoryTearOff node, RedirectingFactoryTearOff other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkTypedefTearOff_typeParameters(
@@ -6313,7 +6372,7 @@
 
   bool checkTypedefTearOff_fileOffset(
       EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkExpression_fileOffset(visitor, node, other);
   }
 
   bool checkArguments_types(
@@ -6336,7 +6395,7 @@
 
   bool checkArguments_fileOffset(
       EquivalenceVisitor visitor, Arguments node, Arguments other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkNamedExpression_name(
@@ -6351,7 +6410,7 @@
 
   bool checkNamedExpression_fileOffset(
       EquivalenceVisitor visitor, NamedExpression node, NamedExpression other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkMapLiteralEntry_key(
@@ -6366,7 +6425,7 @@
 
   bool checkMapLiteralEntry_fileOffset(
       EquivalenceVisitor visitor, MapLiteralEntry node, MapLiteralEntry other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkExpressionStatement_expression(EquivalenceVisitor visitor,
@@ -6374,9 +6433,14 @@
     return visitor.checkNodes(node.expression, other.expression, 'expression');
   }
 
+  bool checkStatement_fileOffset(
+      EquivalenceVisitor visitor, Statement node, Statement other) {
+    return checkTreeNode_fileOffset(visitor, node, other);
+  }
+
   bool checkExpressionStatement_fileOffset(EquivalenceVisitor visitor,
       ExpressionStatement node, ExpressionStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkBlock_statements(
@@ -6393,7 +6457,7 @@
 
   bool checkBlock_fileOffset(
       EquivalenceVisitor visitor, Block node, Block other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkAssertBlock_statements(
@@ -6404,12 +6468,12 @@
 
   bool checkAssertBlock_fileOffset(
       EquivalenceVisitor visitor, AssertBlock node, AssertBlock other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkEmptyStatement_fileOffset(
       EquivalenceVisitor visitor, EmptyStatement node, EmptyStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkAssertStatement_condition(
@@ -6436,7 +6500,7 @@
 
   bool checkAssertStatement_fileOffset(
       EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkLabeledStatement_body(EquivalenceVisitor visitor,
@@ -6446,7 +6510,7 @@
 
   bool checkLabeledStatement_fileOffset(EquivalenceVisitor visitor,
       LabeledStatement node, LabeledStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkBreakStatement_target(
@@ -6456,7 +6520,7 @@
 
   bool checkBreakStatement_fileOffset(
       EquivalenceVisitor visitor, BreakStatement node, BreakStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkWhileStatement_condition(
@@ -6471,7 +6535,7 @@
 
   bool checkWhileStatement_fileOffset(
       EquivalenceVisitor visitor, WhileStatement node, WhileStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkDoStatement_body(
@@ -6486,7 +6550,7 @@
 
   bool checkDoStatement_fileOffset(
       EquivalenceVisitor visitor, DoStatement node, DoStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkForStatement_variables(
@@ -6513,7 +6577,7 @@
 
   bool checkForStatement_fileOffset(
       EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkForInStatement_bodyOffset(
@@ -6543,7 +6607,7 @@
 
   bool checkForInStatement_fileOffset(
       EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkSwitchStatement_expression(
@@ -6559,7 +6623,7 @@
 
   bool checkSwitchStatement_fileOffset(
       EquivalenceVisitor visitor, SwitchStatement node, SwitchStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkContinueSwitchStatement_target(EquivalenceVisitor visitor,
@@ -6569,7 +6633,7 @@
 
   bool checkContinueSwitchStatement_fileOffset(EquivalenceVisitor visitor,
       ContinueSwitchStatement node, ContinueSwitchStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkIfStatement_condition(
@@ -6589,7 +6653,7 @@
 
   bool checkIfStatement_fileOffset(
       EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkReturnStatement_expression(
@@ -6599,7 +6663,7 @@
 
   bool checkReturnStatement_fileOffset(
       EquivalenceVisitor visitor, ReturnStatement node, ReturnStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkTryCatch_body(
@@ -6621,7 +6685,7 @@
 
   bool checkTryCatch_fileOffset(
       EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkTryFinally_body(
@@ -6636,7 +6700,7 @@
 
   bool checkTryFinally_fileOffset(
       EquivalenceVisitor visitor, TryFinally node, TryFinally other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkYieldStatement_expression(
@@ -6651,7 +6715,7 @@
 
   bool checkYieldStatement_fileOffset(
       EquivalenceVisitor visitor, YieldStatement node, YieldStatement other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkVariableDeclaration_fileEqualsOffset(EquivalenceVisitor visitor,
@@ -6695,7 +6759,7 @@
 
   bool checkVariableDeclaration_fileOffset(EquivalenceVisitor visitor,
       VariableDeclaration node, VariableDeclaration other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkFunctionDeclaration_variable(EquivalenceVisitor visitor,
@@ -6710,7 +6774,7 @@
 
   bool checkFunctionDeclaration_fileOffset(EquivalenceVisitor visitor,
       FunctionDeclaration node, FunctionDeclaration other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkStatement_fileOffset(visitor, node, other);
   }
 
   bool checkSwitchCase_expressions(
@@ -6737,7 +6801,7 @@
 
   bool checkSwitchCase_fileOffset(
       EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkCatch_guard(EquivalenceVisitor visitor, Catch node, Catch other) {
@@ -6760,7 +6824,7 @@
 
   bool checkCatch_fileOffset(
       EquivalenceVisitor visitor, Catch node, Catch other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkTypeParameter_flags(
@@ -6797,7 +6861,7 @@
 
   bool checkTypeParameter_fileOffset(
       EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkComponent_problemsAsJson(
@@ -6885,7 +6949,7 @@
 
   bool checkComponent_fileOffset(
       EquivalenceVisitor visitor, Component node, Component other) {
-    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+    return checkTreeNode_fileOffset(visitor, node, other);
   }
 
   bool checkName_text(EquivalenceVisitor visitor, Name node, Name other) {
@@ -7055,29 +7119,34 @@
         visitor.checkNodes, 'typeArguments');
   }
 
+  bool checkPrimitiveConstant_value(EquivalenceVisitor visitor,
+      PrimitiveConstant node, PrimitiveConstant other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
   bool checkNullConstant_value(
       EquivalenceVisitor visitor, NullConstant node, NullConstant other) {
-    return visitor.checkValues(node.value, other.value, 'value');
+    return checkPrimitiveConstant_value(visitor, node, other);
   }
 
   bool checkBoolConstant_value(
       EquivalenceVisitor visitor, BoolConstant node, BoolConstant other) {
-    return visitor.checkValues(node.value, other.value, 'value');
+    return checkPrimitiveConstant_value(visitor, node, other);
   }
 
   bool checkIntConstant_value(
       EquivalenceVisitor visitor, IntConstant node, IntConstant other) {
-    return visitor.checkValues(node.value, other.value, 'value');
+    return checkPrimitiveConstant_value(visitor, node, other);
   }
 
   bool checkDoubleConstant_value(
       EquivalenceVisitor visitor, DoubleConstant node, DoubleConstant other) {
-    return visitor.checkValues(node.value, other.value, 'value');
+    return checkPrimitiveConstant_value(visitor, node, other);
   }
 
   bool checkStringConstant_value(
       EquivalenceVisitor visitor, StringConstant node, StringConstant other) {
-    return visitor.checkValues(node.value, other.value, 'value');
+    return checkPrimitiveConstant_value(visitor, node, other);
   }
 
   bool checkSymbolConstant_name(
diff --git a/pkg/kernel/lib/src/node_creator.dart b/pkg/kernel/lib/src/node_creator.dart
index 7100c5d..8c0337d 100644
--- a/pkg/kernel/lib/src/node_creator.dart
+++ b/pkg/kernel/lib/src/node_creator.dart
@@ -9,6 +9,11 @@
 class NodeCreator {
   final Uri _uri;
 
+  /// File offset counter.
+  ///
+  /// Used to generate distinct file offsets through [_needFileOffset].
+  int _fileOffset = 0;
+
   /// The parent [Component] for all created libraries, classes, extensions,
   /// typedefs and members.
   final Component _component = new Component();
@@ -564,12 +569,15 @@
     return functionDeclaration;
   }
 
+  /// Returns a fresh file offset value.
+  int _needFileOffset() => _fileOffset++;
+
   /// Creates an [Expression] node.
   ///
   /// If there are any pending expressions, one of these is created.
   Expression _createExpression() {
     if (_pendingExpressions.isEmpty) {
-      return NullLiteral();
+      return NullLiteral()..fileOffset = _needFileOffset();
     }
     ExpressionKind kind = _pendingExpressions.keys.first;
     return _createExpressionFromKind(kind);
@@ -583,252 +591,318 @@
     int? index = _pendingExpressions.remove(kind);
     switch (kind) {
       case ExpressionKind.AsExpression:
-        return AsExpression(_createExpression(), _createDartType());
+        return AsExpression(_createExpression(), _createDartType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.AwaitExpression:
-        return AwaitExpression(_createExpression());
+        return AwaitExpression(_createExpression())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.BlockExpression:
         return BlockExpression(
             _createStatementFromKind(StatementKind.Block) as Block,
-            _createExpression());
+            _createExpression())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.BoolLiteral:
-        return BoolLiteral(true);
+        return BoolLiteral(true)..fileOffset = _needFileOffset();
       case ExpressionKind.CheckLibraryIsLoaded:
-        return CheckLibraryIsLoaded(_needLibraryDependency(deferred: true));
+        return CheckLibraryIsLoaded(_needLibraryDependency(deferred: true))
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.ConditionalExpression:
         return ConditionalExpression(_createExpression(), _createExpression(),
-            _createExpression(), _createDartType());
+            _createExpression(), _createDartType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.ConstantExpression:
-        return ConstantExpression(_createConstant(), _createDartType());
+        return ConstantExpression(_createConstant(), _createDartType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.ConstructorInvocation:
         return _createOneOf(_pendingExpressions, kind, index, [
           () => ConstructorInvocation(_needConstructor(), _createArguments(),
-              isConst: false),
+              isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => ConstructorInvocation(_needConstructor(), _createArguments(),
-              isConst: true),
+              isConst: true)
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.ConstructorTearOff:
-        return ConstructorTearOff(_needConstructor());
+        return ConstructorTearOff(_needConstructor())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.DoubleLiteral:
-        return DoubleLiteral(42.5);
+        return DoubleLiteral(42.5)..fileOffset = _needFileOffset();
       case ExpressionKind.DynamicGet:
         return DynamicGet(
-            DynamicAccessKind.Dynamic, _createExpression(), _createName());
+            DynamicAccessKind.Dynamic, _createExpression(), _createName())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.DynamicInvocation:
         return DynamicInvocation(DynamicAccessKind.Dynamic, _createExpression(),
-            _createName(), _createArguments());
+            _createName(), _createArguments())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.DynamicSet:
         return DynamicSet(DynamicAccessKind.Dynamic, _createExpression(),
-            _createName(), _createExpression());
+            _createName(), _createExpression())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.EqualsCall:
         return EqualsCall(_createExpression(), _createExpression(),
             functionType: _createFunctionType(),
-            interfaceTarget: _needProcedure());
+            interfaceTarget: _needProcedure())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.EqualsNull:
-        return EqualsNull(_createExpression());
+        return EqualsNull(_createExpression())..fileOffset = _needFileOffset();
       case ExpressionKind.FileUriExpression:
-        return FileUriExpression(_createExpression(), _uri);
+        return FileUriExpression(_createExpression(), _uri)
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.FunctionExpression:
-        return FunctionExpression(_createFunctionNode());
+        return FunctionExpression(_createFunctionNode())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.FunctionInvocation:
         return FunctionInvocation(FunctionAccessKind.FunctionType,
             _createExpression(), _createArguments(),
-            functionType: _createFunctionType());
+            functionType: _createFunctionType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.FunctionTearOff:
-        return FunctionTearOff(_createExpression());
+        return FunctionTearOff(_createExpression())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.InstanceCreation:
-        return InstanceCreation(_needClass().reference, [], {}, [], []);
+        return InstanceCreation(_needClass().reference, [], {}, [], [])
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.InstanceGet:
         return InstanceGet(
             InstanceAccessKind.Instance, _createExpression(), _createName(),
-            interfaceTarget: _needField(), resultType: _createDartType());
+            interfaceTarget: _needField(), resultType: _createDartType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.InstanceGetterInvocation:
         return InstanceGetterInvocation(InstanceAccessKind.Instance,
             _createExpression(), _createName(), _createArguments(),
-            interfaceTarget: _needField(), functionType: _createFunctionType());
+            interfaceTarget: _needField(), functionType: _createFunctionType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.InstanceInvocation:
         return InstanceInvocation(InstanceAccessKind.Instance,
             _createExpression(), _createName(), _createArguments(),
             interfaceTarget: _needProcedure(),
             functionType: _createFunctionType())
+          ..fileOffset = _needFileOffset()
           ..isBoundsSafe = true;
       case ExpressionKind.InstanceSet:
         return InstanceSet(InstanceAccessKind.Instance, _createExpression(),
             _createName(), _createExpression(),
-            interfaceTarget: _needField());
+            interfaceTarget: _needField())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.InstanceTearOff:
         return InstanceTearOff(
             InstanceAccessKind.Instance, _createExpression(), _createName(),
-            interfaceTarget: _needProcedure(), resultType: _createDartType());
+            interfaceTarget: _needProcedure(), resultType: _createDartType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.Instantiation:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => Instantiation(_createExpression(), []),
-          () => Instantiation(_createExpression(), [_createDartType()]),
+          () => Instantiation(_createExpression(), [])
+            ..fileOffset = _needFileOffset(),
+          () => Instantiation(_createExpression(), [_createDartType()])
+            ..fileOffset = _needFileOffset(),
           () => Instantiation(
-              _createExpression(), [_createDartType(), _createDartType()]),
+              _createExpression(), [_createDartType(), _createDartType()])
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.IntLiteral:
-        return IntLiteral(42);
+        return IntLiteral(42)..fileOffset = _needFileOffset();
       case ExpressionKind.InvalidExpression:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => InvalidExpression(null),
-          () => InvalidExpression('foo'),
-          () => InvalidExpression('foo', _createExpression()),
+          () => InvalidExpression(null)..fileOffset = _needFileOffset(),
+          () => InvalidExpression('foo')..fileOffset = _needFileOffset(),
+          () => InvalidExpression('foo', _createExpression())
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.IsExpression:
         return IsExpression(
           _createExpression(),
           _createDartType(),
-        );
+        )..fileOffset = _needFileOffset();
       case ExpressionKind.Let:
         return Let(
             _createStatementFromKind(StatementKind.VariableDeclaration)
                 as VariableDeclaration,
-            _createExpression());
+            _createExpression())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.ListConcatenation:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => ListConcatenation([], typeArgument: _createDartType()),
+          () => ListConcatenation([], typeArgument: _createDartType())
+            ..fileOffset = _needFileOffset(),
           () => ListConcatenation([_createExpression()],
-              typeArgument: _createDartType()),
+              typeArgument: _createDartType())
+            ..fileOffset = _needFileOffset(),
           () => ListConcatenation([_createExpression(), _createExpression()],
-              typeArgument: _createDartType()),
+              typeArgument: _createDartType())
+            ..fileOffset = _needFileOffset()
         ]);
       case ExpressionKind.ListLiteral:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () =>
-              ListLiteral([], typeArgument: _createDartType(), isConst: false),
+          () => ListLiteral([], typeArgument: _createDartType(), isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => ListLiteral([_createExpression()],
-              typeArgument: _createDartType(), isConst: false),
+              typeArgument: _createDartType(), isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => ListLiteral([_createExpression(), _createExpression()],
-              typeArgument: _createDartType(), isConst: false),
+              typeArgument: _createDartType(), isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => ListLiteral([_createExpression(), _createExpression()],
-              typeArgument: _createDartType(), isConst: true),
+              typeArgument: _createDartType(), isConst: true)
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.LoadLibrary:
-        return LoadLibrary(_needLibraryDependency(deferred: true));
+        return LoadLibrary(_needLibraryDependency(deferred: true))
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.LocalFunctionInvocation:
         return LocalFunctionInvocation(
             _needFunctionDeclaration().variable, _createArguments(),
-            functionType: _createFunctionType());
+            functionType: _createFunctionType())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.LogicalExpression:
         return _createOneOf(_pendingExpressions, kind, index, [
           () => LogicalExpression(_createExpression(),
-              LogicalExpressionOperator.AND, _createExpression()),
+              LogicalExpressionOperator.AND, _createExpression())
+            ..fileOffset = _needFileOffset(),
           () => LogicalExpression(_createExpression(),
-              LogicalExpressionOperator.OR, _createExpression()),
+              LogicalExpressionOperator.OR, _createExpression())
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.MapConcatenation:
         return _createOneOf(_pendingExpressions, kind, index, [
           () => MapConcatenation([],
-              keyType: _createDartType(), valueType: _createDartType()),
+              keyType: _createDartType(), valueType: _createDartType())
+            ..fileOffset = _needFileOffset(),
           () => MapConcatenation([_createExpression()],
-              keyType: _createDartType(), valueType: _createDartType()),
+              keyType: _createDartType(), valueType: _createDartType())
+            ..fileOffset = _needFileOffset(),
           () => MapConcatenation([_createExpression(), _createExpression()],
-              keyType: _createDartType(), valueType: _createDartType()),
+              keyType: _createDartType(), valueType: _createDartType())
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.MapLiteral:
         return _createOneOf(_pendingExpressions, kind, index, [
           () => MapLiteral([],
               keyType: _createDartType(),
               valueType: _createDartType(),
-              isConst: false),
+              isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => MapLiteral([_createMapLiteralEntry()],
               keyType: _createDartType(),
               valueType: _createDartType(),
-              isConst: false),
+              isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => MapLiteral([
                 _createMapLiteralEntry(),
                 _createMapLiteralEntry(),
               ],
                   keyType: _createDartType(),
                   valueType: _createDartType(),
-                  isConst: false),
+                  isConst: false)
+                ..fileOffset = _needFileOffset(),
           () => MapLiteral([
                 _createMapLiteralEntry(),
                 _createMapLiteralEntry(),
               ],
                   keyType: _createDartType(),
                   valueType: _createDartType(),
-                  isConst: true),
+                  isConst: true)
+                ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.Not:
-        return Not(_createExpression());
+        return Not(_createExpression())..fileOffset = _needFileOffset();
       case ExpressionKind.NullCheck:
-        return NullCheck(_createExpression());
+        return NullCheck(_createExpression())..fileOffset = _needFileOffset();
       case ExpressionKind.NullLiteral:
         return NullLiteral();
       case ExpressionKind.RedirectingFactoryTearOff:
-        return RedirectingFactoryTearOff(_needRedirectingFactory());
+        return RedirectingFactoryTearOff(_needRedirectingFactory())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.Rethrow:
-        return Rethrow();
+        return Rethrow()..fileOffset = _needFileOffset();
       case ExpressionKind.SetConcatenation:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => SetConcatenation([], typeArgument: _createDartType()),
+          () => SetConcatenation([], typeArgument: _createDartType())
+            ..fileOffset = _needFileOffset(),
           () => SetConcatenation([_createExpression()],
-              typeArgument: _createDartType()),
+              typeArgument: _createDartType())
+            ..fileOffset = _needFileOffset(),
           () => SetConcatenation([_createExpression(), _createExpression()],
-              typeArgument: _createDartType()),
+              typeArgument: _createDartType())
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.SetLiteral:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => SetLiteral([], typeArgument: _createDartType(), isConst: false),
+          () => SetLiteral([], typeArgument: _createDartType(), isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => SetLiteral([_createExpression()],
-              typeArgument: _createDartType(), isConst: false),
+              typeArgument: _createDartType(), isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => SetLiteral([_createExpression(), _createExpression()],
-              typeArgument: _createDartType(), isConst: false),
+              typeArgument: _createDartType(), isConst: false)
+            ..fileOffset = _needFileOffset(),
           () => SetLiteral([_createExpression(), _createExpression()],
-              typeArgument: _createDartType(), isConst: true),
+              typeArgument: _createDartType(), isConst: true)
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.StaticGet:
-        return StaticGet(_needField());
+        return StaticGet(_needField())..fileOffset = _needFileOffset();
       case ExpressionKind.StaticInvocation:
-        return StaticInvocation(_needProcedure(), _createArguments());
+        return StaticInvocation(_needProcedure(), _createArguments())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.StaticSet:
-        return StaticSet(_needField(), _createExpression());
+        return StaticSet(_needField(), _createExpression())
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.StaticTearOff:
-        return StaticTearOff(_needProcedure());
+        return StaticTearOff(_needProcedure())..fileOffset = _needFileOffset();
       case ExpressionKind.StringConcatenation:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => StringConcatenation([]),
-          () => StringConcatenation([_createExpression()]),
-          () => StringConcatenation([_createExpression(), _createExpression()]),
+          () => StringConcatenation([])..fileOffset = _needFileOffset(),
+          () => StringConcatenation([_createExpression()])
+            ..fileOffset = _needFileOffset(),
+          () => StringConcatenation([_createExpression(), _createExpression()])
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.StringLiteral:
         return StringLiteral('foo');
       case ExpressionKind.SuperMethodInvocation:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => SuperMethodInvocation(_createName(), _createArguments()),
+          () => SuperMethodInvocation(_createName(), _createArguments())
+            ..fileOffset = _needFileOffset(),
           () => SuperMethodInvocation(
-              _createName(), _createArguments(), _needProcedure()),
+              _createName(), _createArguments(), _needProcedure())
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.SuperPropertyGet:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => SuperPropertyGet(_createName()),
-          () => SuperPropertyGet(_createName(), _needField()),
+          () => SuperPropertyGet(_createName())..fileOffset = _needFileOffset(),
+          () => SuperPropertyGet(_createName(), _needField())
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.SuperPropertySet:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => SuperPropertySet(_createName(), _createExpression(), null),
-          () => SuperPropertySet(
-              _createName(), _createExpression(), _needField()),
+          () => SuperPropertySet(_createName(), _createExpression(), null)
+            ..fileOffset = _needFileOffset(),
+          () =>
+              SuperPropertySet(_createName(), _createExpression(), _needField())
+                ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.SymbolLiteral:
-        return SymbolLiteral('foo');
+        return SymbolLiteral('foo')..fileOffset = _needFileOffset();
       case ExpressionKind.ThisExpression:
-        return ThisExpression();
+        return ThisExpression()..fileOffset = _needFileOffset();
       case ExpressionKind.Throw:
-        return Throw(_createExpression());
+        return Throw(_createExpression())..fileOffset = _needFileOffset();
       case ExpressionKind.TypeLiteral:
-        return TypeLiteral(_createDartType());
+        return TypeLiteral(_createDartType())..fileOffset = _needFileOffset();
       case ExpressionKind.TypedefTearOff:
         // TODO(johnniwinther): Add non-trivial cases.
-        return TypedefTearOff([], _createExpression(), []);
+        return TypedefTearOff([], _createExpression(), [])
+          ..fileOffset = _needFileOffset();
       case ExpressionKind.VariableGet:
         return _createOneOf(_pendingExpressions, kind, index, [
-          () => VariableGet(_needVariableDeclaration()),
-          () => VariableGet(_needVariableDeclaration(), _createDartType()),
+          () => VariableGet(_needVariableDeclaration())
+            ..fileOffset = _needFileOffset(),
+          () => VariableGet(_needVariableDeclaration(), _createDartType())
+            ..fileOffset = _needFileOffset(),
         ]);
       case ExpressionKind.VariableSet:
-        return VariableSet(_needVariableDeclaration(), _createExpression());
+        return VariableSet(_needVariableDeclaration(), _createExpression())
+          ..fileOffset = _needFileOffset();
     }
   }
 
@@ -837,7 +911,7 @@
   /// If there are any pending statements, one of these is created.
   Statement _createStatement() {
     if (_pendingStatements.isEmpty) {
-      return EmptyStatement();
+      return EmptyStatement()..fileOffset = _needFileOffset();
     }
     StatementKind kind = _pendingStatements.keys.first;
     return _createStatementFromKind(kind);
@@ -852,99 +926,130 @@
     switch (kind) {
       case StatementKind.AssertBlock:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => AssertBlock([]),
-          () => AssertBlock([_createStatement()]),
-          () => AssertBlock([_createStatement(), _createStatement()]),
+          () => AssertBlock([])..fileOffset = _needFileOffset(),
+          () =>
+              AssertBlock([_createStatement()])..fileOffset = _needFileOffset(),
+          () => AssertBlock([_createStatement(), _createStatement()])
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.AssertStatement:
         return _createOneOf(_pendingStatements, kind, index, [
           () => AssertStatement(_createExpression(),
-              conditionStartOffset: TreeNode.noOffset,
-              conditionEndOffset: TreeNode.noOffset),
+              conditionStartOffset: _needFileOffset(),
+              conditionEndOffset: _needFileOffset())
+            ..fileOffset = _needFileOffset(),
           () => AssertStatement(_createExpression(),
               message: _createExpression(),
-              conditionStartOffset: TreeNode.noOffset,
-              conditionEndOffset: TreeNode.noOffset),
+              conditionStartOffset: _needFileOffset(),
+              conditionEndOffset: _needFileOffset())
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.Block:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => Block([]),
-          () => Block([_createStatement()]),
-          () => Block([_createStatement(), _createStatement()]),
+          () => Block([])..fileOffset = _needFileOffset(),
+          () => Block([_createStatement()])..fileOffset = _needFileOffset(),
+          () => Block([_createStatement(), _createStatement()])
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.BreakStatement:
-        return BreakStatement(_needLabeledStatement());
+        return BreakStatement(_needLabeledStatement())
+          ..fileOffset = _needFileOffset();
       case StatementKind.ContinueSwitchStatement:
-        return ContinueSwitchStatement(_needSwitchCase());
+        return ContinueSwitchStatement(_needSwitchCase())
+          ..fileOffset = _needFileOffset();
       case StatementKind.DoStatement:
-        return DoStatement(_createStatement(), _createExpression());
+        return DoStatement(_createStatement(), _createExpression())
+          ..fileOffset = _needFileOffset();
       case StatementKind.EmptyStatement:
-        return EmptyStatement();
+        return EmptyStatement()..fileOffset = _needFileOffset();
       case StatementKind.ExpressionStatement:
-        return ExpressionStatement(_createExpression());
+        return ExpressionStatement(_createExpression())
+          ..fileOffset = _needFileOffset();
       case StatementKind.ForInStatement:
         return _createOneOf(_pendingStatements, kind, index, [
           () => ForInStatement(_createVariableDeclaration(),
               _createExpression(), _createStatement(),
-              isAsync: false),
+              isAsync: false)
+            ..fileOffset = _needFileOffset(),
           () => ForInStatement(_createVariableDeclaration(),
               _createExpression(), _createStatement(),
-              isAsync: true),
+              isAsync: true)
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.ForStatement:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => ForStatement([], null, [], _createStatement()),
+          () => ForStatement([], null, [], _createStatement())
+            ..fileOffset = _needFileOffset(),
           () => ForStatement([_createVariableDeclaration()],
-              _createExpression(), [_createExpression()], _createStatement()),
+              _createExpression(), [_createExpression()], _createStatement())
+            ..fileOffset = _needFileOffset(),
           () => ForStatement(
               [_createVariableDeclaration(), _createVariableDeclaration()],
               _createExpression(),
               [_createExpression(), _createExpression()],
-              _createStatement()),
+              _createStatement())
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.FunctionDeclaration:
         return FunctionDeclaration(
-            VariableDeclaration(null), _createFunctionNode());
+            VariableDeclaration(null), _createFunctionNode())
+          ..fileOffset = _needFileOffset();
       case StatementKind.IfStatement:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => IfStatement(_createExpression(), _createStatement(), null),
+          () => IfStatement(_createExpression(), _createStatement(), null)
+            ..fileOffset = _needFileOffset(),
           () => IfStatement(
-              _createExpression(), _createStatement(), _createStatement()),
+              _createExpression(), _createStatement(), _createStatement())
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.LabeledStatement:
-        return LabeledStatement(_createStatement());
+        return LabeledStatement(_createStatement())
+          ..fileOffset = _needFileOffset();
       case StatementKind.ReturnStatement:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => ReturnStatement(),
-          () => ReturnStatement(_createExpression()),
+          () => ReturnStatement()..fileOffset = _needFileOffset(),
+          () => ReturnStatement(_createExpression())
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.SwitchStatement:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => SwitchStatement(_createExpression(), []),
-          () => SwitchStatement(_createExpression(), [_createSwitchCase()]),
+          () => SwitchStatement(_createExpression(), [])
+            ..fileOffset = _needFileOffset(),
+          () => SwitchStatement(_createExpression(), [_createSwitchCase()])
+            ..fileOffset = _needFileOffset(),
           () => SwitchStatement(
-              _createExpression(), [_createSwitchCase(), _createSwitchCase()]),
+              _createExpression(), [_createSwitchCase(), _createSwitchCase()])
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.TryCatch:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => TryCatch(_createStatement(), []),
-          () => TryCatch(_createStatement(), [_createCatch()]),
-          () => TryCatch(_createStatement(), [_createCatch(), _createCatch()]),
+          () =>
+              TryCatch(_createStatement(), [])..fileOffset = _needFileOffset(),
+          () => TryCatch(_createStatement(), [_createCatch()])
+            ..fileOffset = _needFileOffset(),
+          () => TryCatch(_createStatement(), [_createCatch(), _createCatch()])
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.TryFinally:
-        return TryFinally(_createStatement(), _createStatement());
+        return TryFinally(_createStatement(), _createStatement())
+          ..fileOffset = _needFileOffset();
       case StatementKind.VariableDeclaration:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => VariableDeclaration('foo'),
-          () => VariableDeclaration('foo', initializer: _createExpression()),
-          () => VariableDeclaration('foo', type: _createDartType()),
+          () => VariableDeclaration('foo')..fileOffset = _needFileOffset(),
+          () => VariableDeclaration('foo', initializer: _createExpression())
+            ..fileOffset = _needFileOffset(),
+          () => VariableDeclaration('foo', type: _createDartType())
+            ..fileOffset = _needFileOffset(),
         ]);
       case StatementKind.WhileStatement:
-        return WhileStatement(_createExpression(), _createStatement());
+        return WhileStatement(_createExpression(), _createStatement())
+          ..fileOffset = _needFileOffset();
       case StatementKind.YieldStatement:
         return _createOneOf(_pendingStatements, kind, index, [
-          () => YieldStatement(_createExpression(), isYieldStar: false),
-          () => YieldStatement(_createExpression(), isYieldStar: true),
+          () => YieldStatement(_createExpression(), isYieldStar: false)
+            ..fileOffset = _needFileOffset(),
+          () => YieldStatement(_createExpression(), isYieldStar: true)
+            ..fileOffset = _needFileOffset(),
         ]);
     }
   }
@@ -1123,7 +1228,7 @@
   /// If there are any pending initializers, one of these is created.
   Initializer _createInitializer() {
     if (_pendingInitializers.isEmpty) {
-      return InvalidInitializer();
+      return InvalidInitializer()..fileOffset = _needFileOffset();
     }
     InitializerKind kind = _pendingInitializers.keys.first;
     return _createInitializerFromKind(kind);
@@ -1140,18 +1245,23 @@
       case InitializerKind.AssertInitializer:
         return AssertInitializer(
             _createStatementFromKind(StatementKind.AssertStatement)
-                as AssertStatement);
+                as AssertStatement)
+          ..fileOffset = _needFileOffset();
       case InitializerKind.FieldInitializer:
         return FieldInitializer(
-            _needField(isStatic: false), _createExpression());
+            _needField(isStatic: false), _createExpression())
+          ..fileOffset = _needFileOffset();
       case InitializerKind.InvalidInitializer:
-        return InvalidInitializer();
+        return InvalidInitializer()..fileOffset = _needFileOffset();
       case InitializerKind.LocalInitializer:
-        return LocalInitializer(_createVariableDeclaration());
+        return LocalInitializer(_createVariableDeclaration())
+          ..fileOffset = _needFileOffset();
       case InitializerKind.RedirectingInitializer:
-        return RedirectingInitializer(_needConstructor(), _createArguments());
+        return RedirectingInitializer(_needConstructor(), _createArguments())
+          ..fileOffset = _needFileOffset();
       case InitializerKind.SuperInitializer:
-        return SuperInitializer(_needConstructor(), _createArguments());
+        return SuperInitializer(_needConstructor(), _createArguments())
+          ..fileOffset = _needFileOffset();
     }
   }
 
@@ -1160,7 +1270,8 @@
   /// If there are any pending members, one of these is created.
   Member _createMember() {
     if (_pendingMembers.isEmpty) {
-      return Field.immutable(_createName(), fileUri: _uri);
+      return Field.immutable(_createName(), fileUri: _uri)
+        ..fileOffset = _needFileOffset();
     }
     MemberKind kind = _pendingMembers.keys.first;
     return _createMemberKind(kind);
@@ -1174,32 +1285,38 @@
     switch (kind) {
       case MemberKind.Constructor:
         return Constructor(_createFunctionNode(),
-            name: _createName(), fileUri: _uri);
+            name: _createName(), fileUri: _uri)
+          ..fileOffset = _needFileOffset();
       case MemberKind.Field:
         return _createOneOf(_pendingMembers, kind, index, [
-          () => Field.mutable(_createName(), fileUri: _uri),
-          () => Field.immutable(_createName(), fileUri: _uri),
+          () => Field.mutable(_createName(), fileUri: _uri)
+            ..fileOffset = _needFileOffset(),
+          () => Field.immutable(_createName(), fileUri: _uri)
+            ..fileOffset = _needFileOffset(),
         ]);
       case MemberKind.Procedure:
         return _createOneOf(_pendingMembers, kind, index, [
           () => Procedure(
               _createName(), ProcedureKind.Method, _createFunctionNode(),
-              fileUri: _uri),
+              fileUri: _uri)
+            ..fileOffset = _needFileOffset(),
           () => Procedure(
               _createName(), ProcedureKind.Operator, _createFunctionNode(),
-              fileUri: _uri),
+              fileUri: _uri)
+            ..fileOffset = _needFileOffset(),
           () => Procedure(
               _createName(), ProcedureKind.Getter, _createFunctionNode(),
-              fileUri: _uri),
+              fileUri: _uri)
+            ..fileOffset = _needFileOffset(),
           () => Procedure(
               _createName(), ProcedureKind.Setter, _createFunctionNode(),
-              fileUri: _uri),
+              fileUri: _uri)
+            ..fileOffset = _needFileOffset(),
         ]);
       case MemberKind.RedirectingFactory:
         return RedirectingFactory(null,
-            name: _createName(),
-            function: _createFunctionNode(),
-            fileUri: _uri);
+            name: _createName(), function: _createFunctionNode(), fileUri: _uri)
+          ..fileOffset = _needFileOffset();
     }
   }
 
@@ -1254,53 +1371,60 @@
       case NodeKind.Arguments:
         return _createOneOf(_pendingNodes, kind, index, [
           // TODO(johnniwinther): Add non-trivial cases.
-          () => Arguments([]),
+          () => Arguments([])..fileOffset = _needFileOffset(),
         ]);
       case NodeKind.Catch:
         // TODO(johnniwinther): Add non-trivial cases.
-        return Catch(null, _createStatement());
+        return Catch(null, _createStatement())..fileOffset = _needFileOffset();
       case NodeKind.Class:
-        return Class(name: 'foo', fileUri: _uri);
+        return Class(name: 'foo', fileUri: _uri)
+          ..fileOffset = _needFileOffset();
       case NodeKind.Combinator:
         return _createOneOf(_pendingNodes, kind, index, [
-          () => Combinator.show([]),
-          () => Combinator.show(['foo']),
-          () => Combinator.show(['foo', 'bar']),
-          () => Combinator.hide([]),
-          () => Combinator.hide(['foo']),
-          () => Combinator.hide(['foo', 'bar']),
+          () => Combinator.show([])..fileOffset = _needFileOffset(),
+          () => Combinator.show(['foo'])..fileOffset = _needFileOffset(),
+          () => Combinator.show(['foo', 'bar'])..fileOffset = _needFileOffset(),
+          () => Combinator.hide([])..fileOffset = _needFileOffset(),
+          () => Combinator.hide(['foo'])..fileOffset = _needFileOffset(),
+          () => Combinator.hide(['foo', 'bar'])..fileOffset = _needFileOffset(),
         ]);
       case NodeKind.Component:
         return _component;
       case NodeKind.Extension:
         // TODO(johnniwinther): Add non-trivial cases.
         return Extension(name: 'foo', fileUri: _uri)
+          ..fileOffset = _needFileOffset()
           ..onType = _createDartType();
       case NodeKind.FunctionNode:
         // TODO(johnniwinther): Add non-trivial cases.
-        return FunctionNode(_createStatement());
+        return FunctionNode(_createStatement())..fileOffset = _needFileOffset();
       case NodeKind.Library:
-        return Library(_uri, fileUri: _uri);
+        return Library(_uri, fileUri: _uri)..fileOffset = _needFileOffset();
       case NodeKind.LibraryDependency:
         return _createOneOf(_pendingNodes, kind, index, [
           // TODO(johnniwinther): Add more cases.
-          () => LibraryDependency.import(_needLibrary()),
-          () => LibraryDependency.import(_needLibrary(), name: 'foo'),
-          () => LibraryDependency.export(_needLibrary()),
+          () => LibraryDependency.import(_needLibrary())
+            ..fileOffset = _needFileOffset(),
+          () => LibraryDependency.import(_needLibrary(), name: 'foo')
+            ..fileOffset = _needFileOffset(),
+          () => LibraryDependency.export(_needLibrary())
+            ..fileOffset = _needFileOffset(),
         ]);
       case NodeKind.LibraryPart:
         // TODO(johnniwinther): Add non-trivial cases.
         // TODO(johnniwinther): Do we need to use a valid part uri?
-        return LibraryPart([], 'foo');
+        return LibraryPart([], 'foo')..fileOffset = _needFileOffset();
       case NodeKind.MapLiteralEntry:
-        return MapLiteralEntry(_createExpression(), _createExpression());
+        return MapLiteralEntry(_createExpression(), _createExpression())
+          ..fileOffset = _needFileOffset();
       case NodeKind.Name:
         return _createOneOf(_pendingNodes, kind, index, [
           () => Name('foo'),
           () => Name('_foo', _needLibrary()),
         ]);
       case NodeKind.NamedExpression:
-        return NamedExpression('foo', _createExpression());
+        return NamedExpression('foo', _createExpression())
+          ..fileOffset = _needFileOffset();
       case NodeKind.NamedType:
         return NamedType('foo', _createDartType());
       case NodeKind.Supertype:
@@ -1312,11 +1436,14 @@
       case NodeKind.SwitchCase:
         // TODO(johnniwinther): Add non-trivial cases.
         return SwitchCase(
-            [NullLiteral()], [TreeNode.noOffset], _createStatement());
+            [NullLiteral()], [TreeNode.noOffset], _createStatement())
+          ..fileOffset = _needFileOffset();
       case NodeKind.TypeParameter:
-        return TypeParameter('foo', _createDartType(), _createDartType());
+        return TypeParameter('foo', _createDartType(), _createDartType())
+          ..fileOffset = _needFileOffset();
       case NodeKind.Typedef:
-        return Typedef('foo', _createDartType(), fileUri: _uri);
+        return Typedef('foo', _createDartType(), fileUri: _uri)
+          ..fileOffset = _needFileOffset();
     }
   }
 
diff --git a/pkg/kernel/test/clone_test.dart b/pkg/kernel/test/clone_test.dart
index 194e4b5..975ca4d 100644
--- a/pkg/kernel/test/clone_test.dart
+++ b/pkg/kernel/test/clone_test.dart
@@ -11,6 +11,7 @@
 
 main() {
   testBodyCloning();
+  testBodyCloningInContext();
   testMemberCloning();
 }
 
@@ -25,6 +26,31 @@
     node.accept(coverageVisitor);
     CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
     TreeNode clone = cloner.clone(node);
+    EquivalenceResult result = checkEquivalence(node, clone,
+        strategy: const NoFileOffsetEquivalenceStrategy());
+    if (!result.isEquivalent) {
+      print(result);
+    }
+    Expect.isTrue(result.isEquivalent, "$node");
+  }
+  Expect.isEmpty(
+      creator.createdKinds.toSet()..removeAll(coverageVisitor.visited),
+      'Nodes not covered in testing.');
+}
+
+void testBodyCloningInContext() {
+  NodeCreator creator =
+      new NodeCreator(initializers: [], members: [], nodes: inBodyNodeKinds);
+  List<Statement> nodes = creator.generateBodies();
+
+  CoverageVisitor coverageVisitor = new CoverageVisitor();
+  for (Statement node in nodes) {
+    node.accept(coverageVisitor);
+    CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
+    // Set up context for [statement].
+    new Procedure(Name('foo'), ProcedureKind.Method, FunctionNode(node),
+        fileUri: dummyUri);
+    TreeNode clone = cloner.cloneInContext(node);
     EquivalenceResult result = checkEquivalence(node, clone);
     if (!result.isEquivalent) {
       print(result);
@@ -110,6 +136,17 @@
       'Nodes not covered in testing.');
 }
 
+class NoFileOffsetEquivalenceStrategy extends EquivalenceStrategy {
+  const NoFileOffsetEquivalenceStrategy();
+
+  @override
+  bool checkTreeNode_fileOffset(
+      EquivalenceVisitor visitor, TreeNode node, TreeNode other) {
+    if (other.fileOffset == TreeNode.noOffset) return true;
+    return super.checkTreeNode_fileOffset(visitor, node, other);
+  }
+}
+
 class MemberEquivalenceStrategy extends EquivalenceStrategy {
   const MemberEquivalenceStrategy();
 
diff --git a/runtime/tests/vm/dart/regress_46797_test.dart b/runtime/tests/vm/dart/regress_46797_test.dart
new file mode 100644
index 0000000..ceb5f0a
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_46797_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2021, 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.
+
+// VMOptions=--optimization-counter-threshold=100
+
+int var74 = -43;
+
+@pragma("vm:never-inline")
+foo(int var74) {
+  if (var74 >>> 0xC == 675872701) {
+    print("side-effect");
+  }
+}
+
+main() {
+  for (var i = 0; i < 200; i++) {
+    foo(43);
+  }
+  foo(-43);
+}
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 9484c260..0262af5 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -3541,8 +3541,8 @@
         const intptr_t kCountLimit = 0x3F;
         intptr_t value = Smi::Cast(constant).Value();
         ASSERT((value >= 0) && (value <= kCountLimit));
-        __ SmiUntag(left);
-        __ LsrImmediate(result, left, value);
+        __ SmiUntag(result, left);
+        __ LsrImmediate(result, result, value);
         if (deopt != nullptr) {
           __ SmiTagAndBranchIfOverflow(result, deopt);
         } else {
diff --git a/tools/VERSION b/tools/VERSION
index 088b16a..29d3552 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 30
+PRERELEASE 31
 PRERELEASE_PATCH 0
\ No newline at end of file