// 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),
    'typeParametersOfFunctionType': FieldRule(isDeclaration: false),
    'positionalParameters': FieldRule(isDeclaration: false),
    'namedParameters': FieldRule(isDeclaration: false),
  },
  '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),
  },
  '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);
}
