// 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.

import 'package:front_end/src/api_prototype/front_end.dart';
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:front_end/src/compute_platform_binaries_location.dart';
import 'package:front_end/src/kernel_generator_impl.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/src/printer.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import 'package:vm/target/vm.dart';

final Uri astLibraryUri = Uri.parse('package:kernel/ast.dart');
final Uri canonicalNameLibraryUri =
    Uri.parse('package:kernel/canonical_name.dart');
Uri computePackageConfig(Uri repoDir) =>
    repoDir.resolve('.dart_tool/package_config.json');

/// Map from names of node classes that declares nominal entities that are _not_
/// referenced through a [Reference] to their identifying name, if any.
///
/// For these classes, [_fieldRuleMap] must defined whether fields of these
/// types should be consider declarations or references to the declarations.
///
/// 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 {
  'VariableDeclaration': 'name',
  'TypeParameter': 'name',
  'LabeledStatement': null,
  'SwitchCase': null,
};

/// Names of non-node, non-enum classes that should be treated as atomic
/// values.
const Set<String> _utilityClassesAsValues = const {
  'Version',
};

/// Names of subclasses of [Node] that do _not_ have `visitX` or `defaultX`
/// methods.
const Set<String> _classesWithoutVisitMethods = const {
  'InvocationExpression',
  'InstanceInvocationExpression',
  'NamedNode',
  'PrimitiveConstant',
};

/// Names of inner [Node] classes that are used as interfaces for (generally)
/// interchangeable classes.
///
/// For instance, when [Expression] is used as the field type, any subtype of
/// [Expression] can be used to populate the field.
const Set<String> _interchangeableClasses = const {
  'Member',
  'Statement',
  'Expression',
  'Constant',
  'DartType',
  'Initializer',
};

/// Names of subclasses of [NamedNode] that do _not_ have `visitXReference` or
/// `defaultXReference` methods.
const Set<String> _classesWithoutVisitReference = const {
  'NamedNode',
  'Library',
  'PrimitiveConstant',
};

/// Map of [FieldRule]s. These consist of a map for each class name, with
/// `null` used for "any class". For each class, a map from field names to
/// [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 = {
  null: {
    'hashCode': null,
    'parent': null,
  },
  'Component': {
    'root': null,
    '_mainMethodName': FieldRule(name: 'mainMethodName'),
    '_mode': FieldRule(name: 'mode'),
  },
  'Library': {
    '_languageVersion': FieldRule(name: 'languageVersion'),
    '_libraryId': null,
    '_classes': FieldRule(name: 'classes'),
    '_typedefs': FieldRule(name: 'typedefs'),
    '_extensions': FieldRule(name: 'extensions'),
    '_fields': FieldRule(name: 'fields'),
    '_procedures': FieldRule(name: 'procedures'),
  },
  'Class': {
    'typeParameters': FieldRule(isDeclaration: true),
    '_constructorsView': null,
    '_constructorsInternal': FieldRule(name: 'constructors'),
    '_fieldsView': null,
    '_fieldsInternal': FieldRule(name: 'fields'),
    '_proceduresView': null,
    '_proceduresInternal': FieldRule(name: 'procedures'),
    '_redirectingFactoriesView': null,
    '_redirectingFactoriesInternal': FieldRule(name: 'redirectingFactories'),
    'lazyBuilder': null,
    'dirty': null,
  },
  'Extension': {
    'typeParameters': FieldRule(isDeclaration: true),
  },
  'Field': {
    'reference': FieldRule(name: 'fieldReference'),
  },
  'TypeParameter': {
    '_variance': FieldRule(name: 'variance'),
  },
  'FunctionNode': {
    '_body': FieldRule(name: 'body'),
    'typeParameters': FieldRule(isDeclaration: true),
    'positionalParameters': FieldRule(isDeclaration: true),
    'namedParameters': FieldRule(isDeclaration: true),
  },
  'Typedef': {
    'typeParameters': FieldRule(isDeclaration: true),
  },
  'TypedefTearOff': {
    'typeParameters': FieldRule(isDeclaration: true),
  },
  'TypedefTearOffConstant': {
    'parameters': FieldRule(isDeclaration: true),
  },
  'LocalInitializer': {
    'variable': FieldRule(isDeclaration: true),
  },
  'Let': {
    'variable': FieldRule(isDeclaration: true),
  },
  'VariableGet': {
    'variable': FieldRule(isDeclaration: false),
  },
  'VariableSet': {
    'variable': FieldRule(isDeclaration: false),
  },
  'LocalFunctionInvocation': {
    'variable': FieldRule(isDeclaration: false),
  },
  'BreakStatement': {
    'target': FieldRule(isDeclaration: false),
  },
  'ForStatement': {
    'variables': FieldRule(isDeclaration: true),
  },
  'ForInStatement': {
    'variable': FieldRule(isDeclaration: true),
  },
  'SwitchStatement': {
    'cases': FieldRule(isDeclaration: true),
  },
  'ContinueSwitchStatement': {
    'target': FieldRule(isDeclaration: false),
  },
  'Catch': {
    'exception': FieldRule(isDeclaration: true),
    'stackTrace': FieldRule(isDeclaration: true),
  },
  'FunctionDeclaration': {
    'variable': FieldRule(isDeclaration: true),
  },
  'FunctionType': {
    'typeParameters': FieldRule(isDeclaration: true),
    '_typedefType': FieldRule(name: 'typedefType'),
  },
  'TypeParameterType': {
    'parameter': FieldRule(isDeclaration: false),
  },
};

/// Data that determines exceptions to how fields are used.
class FieldRule {
  /// If non-null, the field should be accessed by this name.
  ///
  /// This is for instance used for private fields accessed through a public
  /// getter.
  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;

  const FieldRule({this.name, this.isDeclaration});
}

/// Return the [FieldRule] to use for the [field] in [AstClass].
FieldRule? getFieldRule(AstClass astClass, Field field) {
  String name = field.name.text;
  Map<String?, FieldRule?>? leafClassMap = _fieldRuleMap[astClass.name];
  if (leafClassMap != null && leafClassMap.containsKey(name)) {
    return leafClassMap[name];
  }
  Map<String?, FieldRule?>? enclosingClassMap =
      _fieldRuleMap[field.enclosingClass!.name];
  if (enclosingClassMap != null && enclosingClassMap.containsKey(name)) {
    return enclosingClassMap[name];
  }
  Map<String?, FieldRule?>? defaultClassMap = _fieldRuleMap[null];
  if (defaultClassMap != null && defaultClassMap.containsKey(name)) {
    return defaultClassMap[name];
  }
  return new FieldRule(name: name);
}

/// Categorization of classes declared in 'package:kernel/ast.dart'.
enum AstClassKind {
  /// The root [Node] class.
  root,

  /// An abstract node class that is a superclass of a public class. Most of
  /// these have a corresponding `defaultX` visitor method.
  ///
  /// For instance [Statement] and [Expression].
  inner,

  /// A concrete node class. These are the classes for which we have `visitX`
  /// methods.
  ///
  /// For instance [Procedure] and [VariableGet].
  public,

  /// A concrete node class that serves only as an implementation of public
  /// node class.
  ///
  /// For instance [PrivateName] and [PublicName] that implements the public
  /// node [Name].
  implementation,

  /// A node class that serves as an interface.
  ///
  /// For instance `FileUriNode`.
  interface,

  /// A named node class that declares a nominal entity that is used with a
  /// reference.
  named,

  /// A node class that declares a nominal entity but used without reference.
  ///
  /// For instance [VariableDeclaration] which introduces a new entity when it
  /// occurs in a [Block] but is used as a reference when it occurs in a
  /// [VariableGet].
  declarative,

  /// A none-node class that should be treated as a composite structure.
  ///
  /// For instance [ConstantMapEntry] which is a tuple of a [Constant] key and
  /// a [Constant] value.
  utilityAsStructure,

  /// A none-node class that should be treated as an atomic value.
  ///
  /// For instance enum classes.
  utilityAsValue,
}

class AstClass {
  final Class node;
  AstClassKind? _kind;
  final String? declarativeName;
  final bool isInterchangeable;

  AstClass? superclass;
  List<AstClass> interfaces = [];
  List<AstClass> subclasses = [];
  List<AstClass> subtypes = [];

  Map<String, AstField> fields = {};

  AstClass(this.node,
      {this.superclass,
      AstClassKind? kind,
      this.declarativeName,
      required this.isInterchangeable})
      : _kind = kind {
    if (superclass != null) {
      superclass!.subclasses.add(this);
    }
  }

  String get name => node.name;

  AstClassKind get kind {
    if (_kind == null) {
      if (node.isAbstract) {
        if (subclasses.isNotEmpty) {
          if (subclasses.every(
              (element) => element.kind == AstClassKind.implementation)) {
            _kind = AstClassKind.public;
          } else {
            _kind = AstClassKind.inner;
          }
        } else {
          _kind = AstClassKind.interface;
        }
      } else {
        if (node.name.startsWith('_')) {
          _kind = AstClassKind.implementation;
        } else {
          _kind = AstClassKind.public;
        }
      }
    }
    return _kind!;
  }

  /// Returns `true` if this class has a `visitX` or `defaultX` method.
  ///
  /// This is only valid for subclass of [Node].
  bool get hasVisitMethod {
    switch (kind) {
      case AstClassKind.root:
      case AstClassKind.inner:
      case AstClassKind.public:
      case AstClassKind.named:
      case AstClassKind.declarative:
        return !_classesWithoutVisitMethods.contains(name);
      case AstClassKind.implementation:
      case AstClassKind.interface:
      case AstClassKind.utilityAsStructure:
      case AstClassKind.utilityAsValue:
        return false;
    }
  }

  /// Returns `true` if this class has a `visitXReference` or
  /// `defaultXReference` method.
  ///
  /// This is only valid for subclass of [NamedNode] or [Constant].
  bool get hasVisitReferenceMethod {
    switch (kind) {
      case AstClassKind.root:
      case AstClassKind.inner:
      case AstClassKind.public:
      case AstClassKind.named:
      case AstClassKind.declarative:
        return !_classesWithoutVisitReference.contains(name);
      case AstClassKind.implementation:
      case AstClassKind.interface:
      case AstClassKind.utilityAsStructure:
      case AstClassKind.utilityAsValue:
        return false;
    }
  }

  String dump([String indent = ""]) {
    StringBuffer sb = new StringBuffer();
    sb.writeln('${indent}${node.name} ($kind)');
    for (AstField field in fields.values) {
      sb.write(field.dump('${indent}    '));
    }
    for (AstClass subclass in subclasses) {
      sb.write(subclass.dump('${indent}  '));
    }
    return sb.toString();
  }

  @override
  String toString() => '${runtimeType}(${name})';
}

/// Categorization of field types.
enum AstFieldKind {
  /// An atomic non-node value.
  ///
  /// For instance an [int] value.
  value,

  /// A [Node] value that is part of the tree.
  ///
  /// For instance an [Expression] value.
  node,

  /// A [Reference] value.
  reference,

  /// A reference to a declarative [Node].
  ///
  /// For instance the reference to [VariableDeclaration] in [VariableGet].
  use,

  /// A list of values.
  list,

  /// A set of values.
  set,

  /// A map of values.
  map,

  /// A non-node composite value.
  ///
  /// For instance a [ConstantMapEntry] that must be treat as a tuple of
  /// a [Constant] key and a [Constant] value.
  utility,
}

/// Structural description of a field type.
class FieldType {
  final DartType type;
  final AstFieldKind kind;

  FieldType(this.type, this.kind);

  @override
  String toString() => 'FieldType($type,$kind)';
}

class ListFieldType extends FieldType {
  final FieldType elementType;

  ListFieldType(DartType type, this.elementType)
      : super(type, AstFieldKind.list);

  @override
  String toString() => 'ListFieldType($type,$elementType)';
}

class SetFieldType extends FieldType {
  final FieldType elementType;

  SetFieldType(DartType type, this.elementType) : super(type, AstFieldKind.set);

  @override
  String toString() => 'SetFieldType($type,$elementType)';
}

class MapFieldType extends FieldType {
  final FieldType keyType;
  final FieldType valueType;

  MapFieldType(DartType type, this.keyType, this.valueType)
      : super(type, AstFieldKind.map);

  @override
  String toString() => 'MapFieldType($type,$keyType,$valueType)';
}

class UtilityFieldType extends FieldType {
  final AstClass astClass;

  UtilityFieldType(DartType type, this.astClass)
      : super(type, AstFieldKind.utility);

  @override
  String toString() => 'UtilityFieldType($type,$astClass)';
}

class AstField {
  final AstClass astClass;
  final Field node;
  final String name;
  final FieldType type;
  final AstField? parentField;

  AstField(this.astClass, this.node, this.name, this.type, this.parentField);

  String dump([String indent = ""]) {
    StringBuffer sb = new StringBuffer();
    sb.writeln('$indent$name $type');
    return sb.toString();
  }

  @override
  String toString() => '${runtimeType}(${name})';
}

class AstModel {
  final AstClass nodeClass;
  final AstClass namedNodeClass;
  final AstClass constantClass;

  AstModel(this.nodeClass, this.namedNodeClass, this.constantClass);

  /// Returns an [Iterable] for all declarative [Node] classes in the AST model.
  Iterable<AstClass> get declarativeClasses {
    return classes.where((cls) => cls.kind == AstClassKind.declarative);
  }

  /// Returns an [Iterable] for all [Node] (sub)classes in the AST model.
  Iterable<AstClass> get classes sync* {
    Iterable<AstClass> visitClass(AstClass cls) sync* {
      yield cls;
      for (AstClass subclass in cls.subclasses) {
        yield* visitClass(subclass);
      }
    }

    yield* visitClass(nodeClass);
  }
}

/// Computes the [AstModel] from 'package:kernel/ast' using [repoDir] to locate
/// the package config file.
///
/// If [printDump] is `true`, a dump of the model printed to stdout.
Future<AstModel> deriveAstModel(Uri repoDir, {bool printDump: false}) async {
  bool errorsFound = false;
  CompilerOptions options = new CompilerOptions();
  options.sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
  options.compileSdk = true;
  options.target = new VmTarget(new TargetFlags());
  options.librariesSpecificationUri = repoDir.resolve("sdk/lib/libraries.json");
  options.environmentDefines = const {};
  options.packagesFileUri = computePackageConfig(repoDir);
  options.onDiagnostic = (DiagnosticMessage message) {
    printDiagnosticMessage(message, print);
    if (message.severity == Severity.error) {
      errorsFound = true;
    }
  };

  InternalCompilerResult compilerResult = (await kernelForProgramInternal(
      astLibraryUri, options,
      retainDataForTesting: true,
      requireMain: false)) as InternalCompilerResult;
  if (errorsFound) {
    throw 'Errors found';
  }
  ClassHierarchy classHierarchy = compilerResult.classHierarchy!;
  CoreTypes coreTypes = compilerResult.coreTypes!;
  TypeEnvironment typeEnvironment =
      new TypeEnvironment(coreTypes, classHierarchy);

  Library astLibrary = compilerResult.component!.libraries
      .singleWhere((library) => library.importUri == astLibraryUri);

  void reportError(String message) {
    print(message);
    errorsFound = true;
  }

  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)};
  Set<String> interchangeableClasses = _interchangeableClasses.toSet();
  for (Class cls in astLibrary.classes) {
    declarativeClassesNames.remove(cls.name);
    classesWithoutVisitMethods.remove(cls.name);
    classesWithoutVisitReference.remove(cls.name);
    interchangeableClasses.remove(cls.name);

    Map<String, FieldRule?> fieldRules = {...?fieldRuleMap.remove(cls.name)};
    Set<String> renames = {};
    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);
        if (fieldRule != null) {
          if (fieldRule.name != null) {
            renames.add(fieldRule.name!);
          }
        }
        if (!hasFieldRule) {
          if (!cls.isEnum && !field.isStatic && field.name.isPrivate) {
            reportError(
                'Private field `${field.name.text}` in ${parent.name} must '
                'have a field rule.');
          }
        }
        if (nullFieldRules.containsKey(field.name.text)) {
          FieldRule? nullFieldRule = nullFieldRules.remove(field.name.text);
          if (nullFieldRule != null) {
            reportError('Only `null` is allowed for class `null`.');
          }
        }
      }
      parent = parent.superclass;
    }
    for (Procedure procedure in cls.procedures) {
      renames.remove(procedure.name.text);
    }
    if (renames.isNotEmpty) {
      reportError('Unknown procedure(s) for field redirections in '
          '${cls.name}: ${renames}');
    }
    if (fieldRules.isNotEmpty) {
      reportError(
          'Unknown field(s) for rules in ${cls.name}: ${fieldRules.keys}');
    }
  }
  if (declarativeClassesNames.isNotEmpty) {
    reportError('Unknown declarative classes: ${declarativeClassesNames}');
  }
  if (classesWithoutVisitMethods.isNotEmpty) {
    reportError('Unknown classes without visit methods: '
        '${classesWithoutVisitMethods}');
  }
  if (classesWithoutVisitReference.isNotEmpty) {
    reportError('Unknown classes without visit reference methods: '
        '${classesWithoutVisitReference}');
  }
  if (interchangeableClasses.isNotEmpty) {
    reportError('Unknown interchangeable classes: '
        '${interchangeableClasses}');
  }
  if (fieldRuleMap.isNotEmpty) {
    reportError('Unknown classes with field rules: ${fieldRuleMap.keys}');
  }

  Class classNode = astLibrary.classes.singleWhere((cls) => cls.name == 'Node');
  DartType nullableNodeType =
      classNode.getThisType(coreTypes, Nullability.nullable);

  Class classNamedNode =
      astLibrary.classes.singleWhere((cls) => cls.name == 'NamedNode');

  Class classConstant =
      astLibrary.classes.singleWhere((cls) => cls.name == 'Constant');

  Library canonicalNameLibrary = compilerResult.component!.libraries
      .singleWhere((library) => library.importUri == canonicalNameLibraryUri);

  Class referenceClass = canonicalNameLibrary.classes
      .singleWhere((cls) => cls.name == 'Reference');
  DartType nullableReferenceType =
      referenceClass.getThisType(coreTypes, Nullability.nullable);

  Set<Class> declarativeClasses = {};
  Set<DartType> declarativeTypes = {};
  for (String name in _declarativeClassesNames.keys) {
    Class cls = astLibrary.classes.singleWhere((cls) => cls.name == name);
    declarativeClasses.add(cls);
    declarativeTypes.add(cls.getThisType(coreTypes, Nullability.nullable));
  }

  Map<Class, AstClass> classMap = {};

  /// Computes the [AstClass] corresponding to [node] if [node] is declared in
  /// 'package:kernel/ast.dart'.
  AstClass? computeAstClass(Class? node) {
    if (node == null) return null;
    if (node.enclosingLibrary != astLibrary) return null;

    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;
        if (!node.isAbstract &&
            classHierarchy.isSubtypeOf(node, classNamedNode)) {
          kind = AstClassKind.named;
        } else if (declarativeClasses.contains(node)) {
          kind = AstClassKind.declarative;
          declarativeName = _declarativeClassesNames[node.name];
        }
        astClass = new AstClass(node,
            superclass: superclass,
            kind: kind,
            declarativeName: declarativeName,
            isInterchangeable: isInterchangeable);
        for (Supertype supertype in node.implementedTypes) {
          AstClass? astSupertype = computeAstClass(supertype.classNode);
          if (astSupertype != null) {
            astClass.interfaces.add(astSupertype);
            astSupertype.subtypes.add(astClass);
          }
        }
      } else if (node.isEnum || _utilityClassesAsValues.contains(node.name)) {
        astClass = new AstClass(node,
            kind: AstClassKind.utilityAsValue,
            isInterchangeable: isInterchangeable);
      } else {
        AstClass? superclass = computeAstClass(node.superclass);
        astClass = new AstClass(node,
            superclass: superclass,
            kind: AstClassKind.utilityAsStructure,
            isInterchangeable: isInterchangeable);
      }
      classMap[node] = astClass;
    }
    return astClass;
  }

  for (Class cls in astLibrary.classes) {
    computeAstClass(cls);
  }

  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);
      if (rule == null) {
        return;
      }
      DartType type = substitution.substituteType(field.type);

      FieldType computeFieldType(DartType type) {
        bool isDeclarativeType = false;
        for (DartType declarativeType in declarativeTypes) {
          if (type is InterfaceType &&
              typeEnvironment.isSubtypeOf(
                  type, declarativeType, SubtypeCheckMode.withNullabilities)) {
            isDeclarativeType = true;
            break;
          }
        }
        if (isDeclarativeType) {
          if (rule.isDeclaration == null) {
            reportError(
                "No field rule for '${field.name}' in ${astClass.name}.\n"
                "The field type contains the declarative type "
                "'${type.toText(defaultAstTextStrategy)}' "
                "and a rule must therefore specify "
                "whether this constitutes declarative or referential use.");
          }
          if (!rule.isDeclaration!) {
            return new FieldType(type, AstFieldKind.use);
          }
        }
        if (type is InterfaceType &&
            typeEnvironment.isSubtypeOf(type, coreTypes.listNullableRawType,
                SubtypeCheckMode.withNullabilities)) {
          DartType elementType = typeEnvironment
              .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)!
              .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)!;
          return new MapFieldType(type, computeFieldType(typeArguments[0]),
              computeFieldType(typeArguments[1]));
        } else if (type is InterfaceType &&
            typeEnvironment.isSubtypeOf(
                type, nullableNodeType, SubtypeCheckMode.withNullabilities)) {
          return new FieldType(type, AstFieldKind.node);
        } else if (type is InterfaceType &&
            typeEnvironment.isSubtypeOf(type, nullableReferenceType,
                SubtypeCheckMode.withNullabilities)) {
          return new FieldType(type, AstFieldKind.reference);
        } else {
          if (type is InterfaceType) {
            AstClass? astClass = classMap[type.classNode];
            if (astClass != null &&
                astClass.kind == AstClassKind.utilityAsStructure) {
              return new UtilityFieldType(type, astClass);
            }
          }
          return new FieldType(type, AstFieldKind.value);
        }
      }

      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;
    Substitution substitution = Substitution.empty;
    while (parent != null) {
      for (Field field in parent.node.fields) {
        computeAstField(field, substitution);
      }
      parent = parent.superclass;
      if (parent != null) {
        substitution = Substitution.fromSupertype(
            classHierarchy.getClassAsInstanceOf(astClass.node, parent.node)!);
      }
    }
  }

  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());
    for (AstClass astClass in classMap.values) {
      if (astClass != astClassNode && astClass.superclass == null) {
        print(astClass.dump());
      }
    }
  }
  if (errorsFound) {
    throw 'Errors found';
  }
  return new AstModel(astClassNode, astClassNamedNode, astClassConstant);
}
