// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/ast_binary_flags.dart';
import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/linked_unit_context.dart';

/// Accessor for reading AST lazily, or read data that is stored in IDL, but
/// cannot be stored in AST, like inferred types.
class LazyAst {
  static const _defaultTypedKey = 'lazyAst_defaultType';
  static const _genericFunctionTypeIdKey = 'lazyAst_genericFunctionTypeId';
  static const _hasOverrideInferenceKey = 'lazyAst_hasOverrideInference';
  static const _inheritsCovariantKey = 'lazyAst_isCovariant';
  static const _isSimplyBoundedKey = 'lazyAst_simplyBounded';
  static const _returnTypeKey = 'lazyAst_returnType';
  static const _typeInferenceErrorKey = 'lazyAst_typeInferenceError';
  static const _typeKey = 'lazyAst_type';

  final LinkedNode data;

  LazyAst(this.data);

  static DartType getDefaultType(TypeParameter node) {
    return node.getProperty(_defaultTypedKey);
  }

  static int getGenericFunctionTypeId(GenericFunctionType node) {
    return node.getProperty(_genericFunctionTypeIdKey);
  }

  static bool getInheritsCovariant(AstNode node) {
    return node.getProperty(_inheritsCovariantKey) ?? false;
  }

  static DartType getReturnType(AstNode node) {
    return node.getProperty(_returnTypeKey);
  }

  static DartType getType(AstNode node) {
    return node.getProperty(_typeKey);
  }

  static TopLevelInferenceError getTypeInferenceError(AstNode node) {
    return node.getProperty(_typeInferenceErrorKey);
  }

  static bool hasOverrideInferenceDone(AstNode node) {
    return node.getProperty(_hasOverrideInferenceKey) ?? false;
  }

  static bool isSimplyBounded(AstNode node) {
    return node.getProperty(_isSimplyBoundedKey);
  }

  static void setDefaultType(TypeParameter node, DartType type) {
    node.setProperty(_defaultTypedKey, type);
  }

  static void setGenericFunctionTypeId(GenericFunctionType node, int id) {
    node.setProperty(_genericFunctionTypeIdKey, id);
  }

  static void setInheritsCovariant(AstNode node, bool value) {
    node.setProperty(_inheritsCovariantKey, value);
  }

  static void setOverrideInferenceDone(AstNode node) {
    node.setProperty(_hasOverrideInferenceKey, true);
  }

  static void setReturnType(AstNode node, DartType type) {
    node.setProperty(_returnTypeKey, type);
  }

  static void setSimplyBounded(AstNode node, bool simplyBounded) {
    node.setProperty(_isSimplyBoundedKey, simplyBounded);
  }

  static void setType(AstNode node, DartType type) {
    node.setProperty(_typeKey, type);
  }

  static void setTypeInferenceError(
      AstNode node, TopLevelInferenceError error) {
    node.setProperty(_typeInferenceErrorKey, error);
  }
}

class LazyClassDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasExtendsClause = false;
  bool _hasImplementsClause = false;
  bool _hasMembers = false;
  bool _hasMetadata = false;
  bool _hasWithClause = false;

  LazyClassDeclaration(this.data);

  static LazyClassDeclaration get(ClassDeclaration node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    ClassDeclaration node,
  ) {
    var lazy = LazyClassDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    ClassDeclaration node,
  ) {
    var lazy = LazyClassDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    ClassDeclaration node,
  ) {
    var lazy = LazyClassDeclaration.get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readExtendsClause(
    AstBinaryReader reader,
    ClassDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasExtendsClause) {
      node.extendsClause = reader.readNode(
        lazy.data.classDeclaration_extendsClause,
      );
      lazy._hasExtendsClause = true;
    }
  }

  static void readImplementsClause(
    AstBinaryReader reader,
    ClassDeclaration node,
  ) {
    var lazy = LazyClassDeclaration.get(node);
    if (lazy != null && !lazy._hasImplementsClause) {
      node.implementsClause = reader.readNode(
        lazy.data.classOrMixinDeclaration_implementsClause,
      );
      lazy._hasImplementsClause = true;
    }
  }

  static void readMembers(
    AstBinaryReader reader,
    ClassDeclaration node,
  ) {
    var lazy = LazyClassDeclaration.get(node);
    if (lazy != null && !lazy._hasMembers) {
      var dataList = lazy.data.classOrMixinDeclaration_members;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.members[i] = reader.readNode(data);
      }
      lazy._hasMembers = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    ClassDeclaration node,
  ) {
    var lazy = LazyClassDeclaration.get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readWithClause(
    AstBinaryReader reader,
    ClassDeclaration node,
  ) {
    var lazy = LazyClassDeclaration.get(node);
    if (lazy != null && !lazy._hasWithClause) {
      node.withClause = reader.readNode(
        lazy.data.classDeclaration_withClause,
      );
      lazy._hasWithClause = true;
    }
  }

  static void setData(ClassDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyClassDeclaration(data));
    LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
  }
}

class LazyClassTypeAlias {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasImplementsClause = false;
  bool _hasMetadata = false;
  bool _hasSuperclass = false;
  bool _hasWithClause = false;

  LazyClassTypeAlias(this.data);

  static LazyClassTypeAlias get(ClassTypeAlias node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    ClassTypeAlias node,
  ) {
    var lazy = LazyClassTypeAlias.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    ClassTypeAlias node,
  ) {
    var lazy = LazyClassTypeAlias.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    ClassTypeAlias node,
  ) {
    var lazy = LazyClassTypeAlias.get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readImplementsClause(
    AstBinaryReader reader,
    ClassTypeAlias node,
  ) {
    var lazy = LazyClassTypeAlias.get(node);
    if (lazy != null && !lazy._hasImplementsClause) {
      node.implementsClause = reader.readNode(
        lazy.data.classTypeAlias_implementsClause,
      );
      lazy._hasImplementsClause = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    ClassTypeAlias node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readSuperclass(
    AstBinaryReader reader,
    ClassTypeAlias node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (!lazy._hasSuperclass) {
        node.superclass = reader.readNode(
          lazy.data.classTypeAlias_superclass,
        );
        lazy._hasSuperclass = true;
      }
    }
  }

  static void readWithClause(
    AstBinaryReader reader,
    ClassTypeAlias node,
  ) {
    var lazy = LazyClassTypeAlias.get(node);
    if (lazy != null && !lazy._hasWithClause) {
      node.withClause = reader.readNode(
        lazy.data.classTypeAlias_withClause,
      );
      lazy._hasWithClause = true;
    }
  }

  static void setData(ClassTypeAlias node, LinkedNode data) {
    node.setProperty(_key, LazyClassTypeAlias(data));
    LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
  }
}

class LazyCompilationUnit {
  static const _key = 'lazyAst';

  final LinkedNode data;

  LazyCompilationUnit(this.data);

  static LazyCompilationUnit get(CompilationUnit node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    CompilationUnit node,
  ) {
    var lazy = LazyCompilationUnit.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    CompilationUnit node,
  ) {
    var lazy = LazyCompilationUnit.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static void setData(CompilationUnit node, LinkedNode data) {
    node.setProperty(_key, LazyCompilationUnit(data));
  }
}

class LazyConstructorDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasBody = false;
  bool _hasDocumentationComment = false;
  bool _hasFormalParameters = false;
  bool _hasInitializers = false;
  bool _hasMetadata = false;
  bool _hasRedirectedConstructor = false;

  LazyConstructorDeclaration(this.data);

  static LazyConstructorDeclaration get(ConstructorDeclaration node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    ConstructorDeclaration node,
  ) {
    var lazy = LazyConstructorDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    ConstructorDeclaration node,
  ) {
    var lazy = LazyConstructorDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static void readBody(
    AstBinaryReader reader,
    ConstructorDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasBody) {
      node.body = reader.readNode(
        lazy.data.constructorDeclaration_body,
      );
      lazy._hasBody = true;
    }
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    ConstructorDeclaration node,
  ) {
    var lazy = LazyConstructorDeclaration.get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readFormalParameters(
    AstBinaryReader reader,
    ConstructorDeclaration node,
  ) {
    var lazy = LazyConstructorDeclaration.get(node);
    if (lazy != null && !lazy._hasFormalParameters) {
      node.parameters = reader.readNode(
        lazy.data.constructorDeclaration_parameters,
      );
      lazy._hasFormalParameters = true;
    }
  }

  static void readInitializers(
    AstBinaryReader reader,
    ConstructorDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasInitializers) {
      var dataList = lazy.data.constructorDeclaration_initializers;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.initializers[i] = reader.readNode(data);
      }
      lazy._hasInitializers = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    ConstructorDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readRedirectedConstructor(
    AstBinaryReader reader,
    ConstructorDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasRedirectedConstructor) {
      node.redirectedConstructor = reader.readNode(
        lazy.data.constructorDeclaration_redirectedConstructor,
      );
      lazy._hasRedirectedConstructor = true;
    }
  }

  static void setData(ConstructorDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyConstructorDeclaration(data));
  }
}

class LazyDirective {
  static const _key = 'lazyAst';
  static const _uriKey = 'lazyAst_selectedUri';

  final LinkedNode data;

  bool _hasMetadata = false;

  LazyDirective(this.data);

  static LazyDirective get(Directive node) {
    return node.getProperty(_key);
  }

  static String getSelectedUri(UriBasedDirective node) {
    return node.getProperty(_uriKey);
  }

  static void readMetadata(AstBinaryReader reader, Directive node) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void setData(Directive node, LinkedNode data) {
    node.setProperty(_key, LazyDirective(data));
    if (node is NamespaceDirective) {
      node.setProperty(_uriKey, data.namespaceDirective_selectedUri);
    }
  }

  static void setSelectedUri(UriBasedDirective node, String uriStr) {
    node.setProperty(_uriKey, uriStr);
  }
}

class LazyEnumConstantDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasMetadata = false;

  LazyEnumConstantDeclaration(this.data);

  static LazyEnumConstantDeclaration get(EnumConstantDeclaration node) {
    return node.getProperty(_key);
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    EnumConstantDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    EnumConstantDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void setData(EnumConstantDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyEnumConstantDeclaration(data));
  }
}

class LazyEnumDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasConstants = false;
  bool _hasDocumentationComment = false;
  bool _hasMetadata = false;

  LazyEnumDeclaration(this.data);

  static LazyEnumDeclaration get(EnumDeclaration node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    EnumDeclaration node,
  ) {
    var lazy = LazyEnumDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    EnumDeclaration node,
  ) {
    var lazy = LazyEnumDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static void readConstants(
    AstBinaryReader reader,
    EnumDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasConstants) {
      var dataList = lazy.data.enumDeclaration_constants;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.constants[i] = reader.readNode(data);
      }
      lazy._hasConstants = true;
    }
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    EnumDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    EnumDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void setData(EnumDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyEnumDeclaration(data));
  }
}

class LazyFieldDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasMetadata = false;

  LazyFieldDeclaration(this.data);

  static LazyFieldDeclaration get(FieldDeclaration node) {
    return node.getProperty(_key);
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    FieldDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    FieldDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void setData(FieldDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyFieldDeclaration(data));
  }
}

class LazyFormalParameter {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDefaultValue = false;
  bool _hasFormalParameters = false;
  bool _hasMetadata = false;
  bool _hasType = false;
  bool _hasTypeInferenceError = false;
  bool _hasTypeNode = false;

  LazyFormalParameter(this.data);

  static LazyFormalParameter get(FormalParameter node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    FormalParameter node,
  ) {
    var lazy = LazyFormalParameter.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    FormalParameter node,
  ) {
    var lazy = LazyFormalParameter.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static DartType getType(
    AstBinaryReader reader,
    FormalParameter node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (!lazy._hasType) {
        var type = reader.readType(lazy.data.actualType);
        LazyAst.setType(node, type);
        lazy._hasType = true;
      }
    }
    return LazyAst.getType(node);
  }

  static TopLevelInferenceError getTypeInferenceError(FormalParameter node) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasTypeInferenceError) {
      var error = lazy.data.topLevelTypeInferenceError;
      LazyAst.setTypeInferenceError(node, error);
      lazy._hasTypeInferenceError = true;
    }
    return LazyAst.getTypeInferenceError(node);
  }

  static bool hasDefaultValue(DefaultFormalParameter node) {
    var lazy = LazyFormalParameter.get(node);
    if (lazy != null) {
      return AstBinaryFlags.hasInitializer(lazy.data.flags);
    } else {
      return node.defaultValue != null;
    }
  }

  static void readDefaultValue(
    AstBinaryReader reader,
    DefaultFormalParameter node,
  ) {
    if (reader.isLazy) {
      var lazy = LazyFormalParameter.get(node);
      if (lazy != null && !lazy._hasDefaultValue) {
        node.defaultValue = reader.readNode(
          lazy.data.defaultFormalParameter_defaultValue,
        );
        lazy._hasDefaultValue = true;
      }
    }
  }

  static void readFormalParameters(
    AstBinaryReader reader,
    FormalParameter node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasFormalParameters) {
      if (node is FunctionTypedFormalParameter) {
        node.parameters = reader.readNode(
          lazy.data.functionTypedFormalParameter_formalParameters,
        );
      } else if (node is FieldFormalParameter) {
        node.parameters = reader.readNode(
          lazy.data.fieldFormalParameter_formalParameters,
        );
      }
      lazy._hasFormalParameters = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    FormalParameter node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.normalFormalParameter_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readTypeNode(
    AstBinaryReader reader,
    FormalParameter node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (lazy != null && !lazy._hasTypeNode) {
        if (node is SimpleFormalParameter) {
          node.type = reader.readNode(
            lazy.data.simpleFormalParameter_type,
          );
        }
        lazy._hasTypeNode = true;
      }
    }
  }

  static void setData(FormalParameter node, LinkedNode data) {
    node.setProperty(_key, LazyFormalParameter(data));
  }
}

class LazyFunctionDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasMetadata = false;
  bool _hasReturnType = false;
  bool _hasReturnTypeNode = false;

  LazyFunctionDeclaration(this.data);

  static LazyFunctionDeclaration get(FunctionDeclaration node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    FunctionDeclaration node,
  ) {
    var lazy = LazyFunctionDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    FunctionDeclaration node,
  ) {
    var lazy = LazyFunctionDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static DartType getReturnType(
    AstBinaryReader reader,
    FunctionDeclaration node,
  ) {
    readFunctionExpression(reader, node);
    if (reader.isLazy) {
      var lazy = get(node);
      if (!lazy._hasReturnType) {
        var type = reader.readType(lazy.data.actualReturnType);
        LazyAst.setReturnType(node, type);
        lazy._hasReturnType = true;
      }
    }
    return LazyAst.getReturnType(node);
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    FunctionDeclaration node,
  ) {
    var lazy = LazyFunctionDeclaration.get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readFunctionExpression(
    AstBinaryReader reader,
    FunctionDeclaration node,
  ) {
    if (node.functionExpression == null) {
      var lazy = LazyFunctionDeclaration.get(node);
      node.functionExpression = reader.readNode(
        lazy.data.functionDeclaration_functionExpression,
      );
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    FunctionDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readReturnTypeNode(
    AstBinaryReader reader,
    FunctionDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasReturnTypeNode) {
      node.returnType = reader.readNode(
        lazy.data.functionDeclaration_returnType,
      );
      lazy._hasReturnTypeNode = true;
    }
  }

  static void setData(FunctionDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyFunctionDeclaration(data));
  }
}

class LazyFunctionExpression {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasBody = false;
  bool _hasFormalParameters = false;

  LazyFunctionExpression(this.data);

  static LazyFunctionExpression get(FunctionExpression node) {
    return node.getProperty(_key);
  }

  static bool isAsynchronous(FunctionExpression node) {
    var lazy = get(node);
    if (lazy != null) {
      return AstBinaryFlags.isAsync(lazy.data.flags);
    } else {
      return node.body.isAsynchronous;
    }
  }

  static bool isGenerator(FunctionExpression node) {
    var lazy = get(node);
    if (lazy != null) {
      return AstBinaryFlags.isGenerator(lazy.data.flags);
    } else {
      return node.body.isGenerator;
    }
  }

  static void readBody(
    AstBinaryReader reader,
    FunctionExpression node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasBody) {
      node.body = reader.readNode(
        lazy.data.functionExpression_body,
      );
      lazy._hasBody = true;
    }
  }

  static void readFormalParameters(
    AstBinaryReader reader,
    FunctionExpression node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasFormalParameters) {
      node.parameters = reader.readNode(
        lazy.data.functionExpression_formalParameters,
      );
      lazy._hasFormalParameters = true;
    }
  }

  static void setData(FunctionExpression node, LinkedNode data) {
    node.setProperty(_key, LazyFunctionExpression(data));
  }
}

class LazyFunctionTypeAlias {
  static const _key = 'lazyAst';
  static const _hasSelfReferenceKey = 'lazyAst_hasSelfReferenceKey';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasFormalParameters = false;
  bool _hasMetadata = false;
  bool _hasReturnType = false;
  bool _hasReturnTypeNode = false;

  LazyFunctionTypeAlias(this.data);

  static LazyFunctionTypeAlias get(FunctionTypeAlias node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    FunctionTypeAlias node,
  ) {
    var lazy = LazyFunctionTypeAlias.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    FunctionTypeAlias node,
  ) {
    var lazy = LazyFunctionTypeAlias.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static bool getHasSelfReference(FunctionTypeAlias node) {
    return node.getProperty(_hasSelfReferenceKey);
  }

  static DartType getReturnType(
    AstBinaryReader reader,
    FunctionTypeAlias node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (!lazy._hasReturnType) {
        var type = reader.readType(lazy.data.actualReturnType);
        LazyAst.setReturnType(node, type);
        lazy._hasReturnType = true;
      }
    }
    return LazyAst.getReturnType(node);
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    FunctionTypeAlias node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readFormalParameters(
    AstBinaryReader reader,
    FunctionTypeAlias node,
  ) {
    var lazy = LazyFunctionTypeAlias.get(node);
    if (lazy != null && !lazy._hasFormalParameters) {
      node.parameters = reader.readNode(
        lazy.data.functionTypeAlias_formalParameters,
      );
      lazy._hasFormalParameters = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    FunctionTypeAlias node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readReturnTypeNode(
    AstBinaryReader reader,
    FunctionTypeAlias node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasReturnTypeNode) {
      node.returnType = reader.readNode(
        lazy.data.functionTypeAlias_returnType,
      );
      lazy._hasReturnTypeNode = true;
    }
  }

  static void setData(FunctionTypeAlias node, LinkedNode data) {
    node.setProperty(_key, LazyFunctionTypeAlias(data));
    LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
  }

  static void setHasSelfReference(FunctionTypeAlias node, bool value) {
    node.setProperty(_hasSelfReferenceKey, value);
  }
}

class LazyGenericTypeAlias {
  static const _key = 'lazyAst';
  static const _hasSelfReferenceKey = 'lazyAst_hasSelfReferenceKey';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasFunction = false;
  bool _hasMetadata = false;

  LazyGenericTypeAlias(this.data);

  static LazyGenericTypeAlias get(GenericTypeAlias node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    GenericTypeAlias node,
  ) {
    var lazy = LazyGenericTypeAlias.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    GenericTypeAlias node,
  ) {
    var lazy = LazyGenericTypeAlias.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static bool getHasSelfReference(GenericTypeAlias node) {
    return node.getProperty(_hasSelfReferenceKey);
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    GenericTypeAlias node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readFunctionType(
    AstBinaryReader reader,
    GenericTypeAlias node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasFunction) {
      node.functionType = reader.readNode(
        lazy.data.genericTypeAlias_functionType,
      );
      lazy._hasFunction = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    GenericTypeAlias node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void setData(GenericTypeAlias node, LinkedNode data) {
    node.setProperty(_key, LazyGenericTypeAlias(data));
    LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
  }

  static void setHasSelfReference(GenericTypeAlias node, bool value) {
    node.setProperty(_hasSelfReferenceKey, value);
  }
}

class LazyMethodDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasBody = false;
  bool _hasDocumentationComment = false;
  bool _hasFormalParameters = false;
  bool _hasMetadata = false;
  bool _hasReturnType = false;
  bool _hasReturnTypeNode = false;

  LazyMethodDeclaration(this.data);

  static LazyMethodDeclaration get(MethodDeclaration node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    MethodDeclaration node,
  ) {
    var lazy = LazyMethodDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    MethodDeclaration node,
  ) {
    var lazy = LazyMethodDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static DartType getReturnType(
    AstBinaryReader reader,
    MethodDeclaration node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (!lazy._hasReturnType) {
        var type = reader.readType(lazy.data.actualReturnType);
        LazyAst.setReturnType(node, type);
        lazy._hasReturnType = true;
      }
    }
    return LazyAst.getReturnType(node);
  }

  static bool isAbstract(MethodDeclaration node) {
    var lazy = get(node);
    if (lazy != null) {
      return AstBinaryFlags.isAbstract(lazy.data.flags);
    } else {
      return node.isAbstract;
    }
  }

  static bool isAsynchronous(MethodDeclaration node) {
    var lazy = get(node);
    if (lazy != null) {
      return AstBinaryFlags.isAsync(lazy.data.flags);
    } else {
      return node.body.isAsynchronous;
    }
  }

  static bool isGenerator(MethodDeclaration node) {
    var lazy = get(node);
    if (lazy != null) {
      return AstBinaryFlags.isGenerator(lazy.data.flags);
    } else {
      return node.body.isGenerator;
    }
  }

  static void readBody(
    AstBinaryReader reader,
    MethodDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasBody) {
      node.body = reader.readNode(
        lazy.data.methodDeclaration_body,
      );
      lazy._hasBody = true;
    }
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    MethodDeclaration node,
  ) {
    var lazy = LazyMethodDeclaration.get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readFormalParameters(
    AstBinaryReader reader,
    MethodDeclaration node,
  ) {
    var lazy = LazyMethodDeclaration.get(node);
    if (lazy != null && !lazy._hasFormalParameters) {
      node.parameters = reader.readNode(
        lazy.data.methodDeclaration_formalParameters,
      );
      lazy._hasFormalParameters = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    MethodDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readReturnTypeNode(
    AstBinaryReader reader,
    MethodDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasReturnTypeNode) {
      node.returnType = reader.readNode(
        lazy.data.methodDeclaration_returnType,
      );
      lazy._hasReturnTypeNode = true;
    }
  }

  static void setData(MethodDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyMethodDeclaration(data));
  }
}

class LazyMixinDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasOnClause = false;
  bool _hasImplementsClause = false;
  bool _hasMembers = false;
  bool _hasMetadata = false;

  List<String> _superInvokedNames;

  LazyMixinDeclaration(MixinDeclaration node, this.data) {
    node.setProperty(_key, this);
    if (data != null) {
      LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
    }
  }

  List<String> getSuperInvokedNames() {
    return _superInvokedNames ??= data.mixinDeclaration_superInvokedNames;
  }

  void put(LinkedNodeBuilder builder) {
    builder.mixinDeclaration_superInvokedNames = _superInvokedNames ?? [];
  }

  void setSuperInvokedNames(List<String> value) {
    _superInvokedNames = value;
  }

  static LazyMixinDeclaration get(MixinDeclaration node) {
    LazyMixinDeclaration lazy = node.getProperty(_key);
    if (lazy == null) {
      return LazyMixinDeclaration(node, null);
    }
    return lazy;
  }

  static int getCodeLength(
    LinkedUnitContext context,
    MixinDeclaration node,
  ) {
    var lazy = LazyMixinDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    MixinDeclaration node,
  ) {
    var lazy = LazyMixinDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    MixinDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy.data != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readImplementsClause(
    AstBinaryReader reader,
    MixinDeclarationImpl node,
  ) {
    var lazy = get(node);
    if (lazy.data != null && !lazy._hasImplementsClause) {
      node.implementsClause = reader.readNode(
        lazy.data.classOrMixinDeclaration_implementsClause,
      );
      lazy._hasImplementsClause = true;
    }
  }

  static void readMembers(
    AstBinaryReader reader,
    MixinDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy.data != null && !lazy._hasMembers) {
      var dataList = lazy.data.classOrMixinDeclaration_members;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.members[i] = reader.readNode(data);
      }
      lazy._hasMembers = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    MixinDeclaration node,
  ) {
    var lazy = LazyMixinDeclaration.get(node);
    if (lazy.data != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void readOnClause(
    AstBinaryReader reader,
    MixinDeclarationImpl node,
  ) {
    var lazy = get(node);
    if (lazy.data != null && !lazy._hasOnClause) {
      node.onClause = reader.readNode(
        lazy.data.mixinDeclaration_onClause,
      );
      lazy._hasOnClause = true;
    }
  }
}

class LazyTopLevelVariableDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasDocumentationComment = false;
  bool _hasMetadata = false;

  LazyTopLevelVariableDeclaration(this.data);

  static LazyTopLevelVariableDeclaration get(TopLevelVariableDeclaration node) {
    return node.getProperty(_key);
  }

  static void readDocumentationComment(
    LinkedUnitContext context,
    TopLevelVariableDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasDocumentationComment) {
      node.documentationComment = context.createComment(lazy.data);
      lazy._hasDocumentationComment = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    TopLevelVariableDeclaration node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void setData(TopLevelVariableDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyTopLevelVariableDeclaration(data));
  }
}

class LazyTypeParameter {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasBound = false;
  bool _hasDefaultType = false;
  bool _hasMetadata = false;

  LazyTypeParameter(this.data);

  static LazyTypeParameter get(TypeParameter node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    TypeParameter node,
  ) {
    var lazy = LazyTypeParameter.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    return node.length;
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    TypeParameter node,
  ) {
    var lazy = LazyTypeParameter.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    return node.offset;
  }

  static DartType getDefaultType(AstBinaryReader reader, TypeParameter node) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasDefaultType) {
      lazy._hasDefaultType = true;
      var type = reader.readType(lazy.data.typeParameter_defaultType);
      LazyAst.setDefaultType(node, type);
      return type;
    }
    return LazyAst.getDefaultType(node);
  }

  static void readBound(AstBinaryReader reader, TypeParameter node) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasBound) {
      node.bound = reader.readNode(lazy.data.typeParameter_bound);
      lazy._hasBound = true;
    }
  }

  static void readMetadata(
    AstBinaryReader reader,
    TypeParameter node,
  ) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasMetadata) {
      var dataList = lazy.data.annotatedNode_metadata;
      for (var i = 0; i < dataList.length; ++i) {
        var data = dataList[i];
        node.metadata[i] = reader.readNode(data);
      }
      lazy._hasMetadata = true;
    }
  }

  static void setData(TypeParameter node, LinkedNode data) {
    node.setProperty(_key, LazyTypeParameter(data));
  }
}

class LazyVariableDeclaration {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasInitializer = false;
  bool _hasType = false;
  bool _hasTypeInferenceError = false;

  LazyVariableDeclaration(this.data);

  static LazyVariableDeclaration get(VariableDeclaration node) {
    return node.getProperty(_key);
  }

  static int getCodeLength(
    LinkedUnitContext context,
    VariableDeclaration node,
  ) {
    var lazy = LazyVariableDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
    }
    VariableDeclarationList parent = node.parent;
    if (parent.variables[0] == node) {
      return node.end - parent.offset;
    } else {
      return node.end - node.offset;
    }
  }

  static int getCodeOffset(
    LinkedUnitContext context,
    VariableDeclaration node,
  ) {
    var lazy = LazyVariableDeclaration.get(node);
    if (lazy != null) {
      var lazy = get(node);
      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
    }
    VariableDeclarationList parent = node.parent;
    if (parent.variables[0] == node) {
      return parent.offset;
    } else {
      return node.offset;
    }
  }

  static DartType getType(
    AstBinaryReader reader,
    VariableDeclaration node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (!lazy._hasType) {
        var type = reader.readType(lazy.data.actualType);
        LazyAst.setType(node, type);
        lazy._hasType = true;
      }
    }
    return LazyAst.getType(node);
  }

  static TopLevelInferenceError getTypeInferenceError(
      VariableDeclaration node) {
    var lazy = get(node);
    if (lazy != null && !lazy._hasTypeInferenceError) {
      var error = lazy.data.topLevelTypeInferenceError;
      LazyAst.setTypeInferenceError(node, error);
      lazy._hasTypeInferenceError = true;
    }
    return LazyAst.getTypeInferenceError(node);
  }

  static bool hasInitializer(VariableDeclaration node) {
    var lazy = get(node);
    if (lazy != null) {
      return AstBinaryFlags.hasInitializer(lazy.data.flags);
    } else {
      return node.initializer != null;
    }
  }

  static void readInitializer(
    AstBinaryReader reader,
    VariableDeclaration node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (lazy != null && !lazy._hasInitializer) {
        node.initializer = reader.readNode(
          lazy.data.variableDeclaration_initializer,
        );
        lazy._hasInitializer = true;
      }
    }
  }

  static void setData(VariableDeclaration node, LinkedNode data) {
    node.setProperty(_key, LazyVariableDeclaration(data));
  }
}

class LazyVariableDeclarationList {
  static const _key = 'lazyAst';

  final LinkedNode data;

  bool _hasTypeNode = false;

  LazyVariableDeclarationList(this.data);

  static LazyVariableDeclarationList get(VariableDeclarationList node) {
    return node.getProperty(_key);
  }

  static void readTypeNode(
    AstBinaryReader reader,
    VariableDeclarationList node,
  ) {
    if (reader.isLazy) {
      var lazy = get(node);
      if (!lazy._hasTypeNode) {
        node.type = reader.readNode(
          lazy.data.variableDeclarationList_type,
        );
        lazy._hasTypeNode = true;
      }
    }
  }

  static void setData(VariableDeclarationList node, LinkedNode data) {
    node.setProperty(_key, LazyVariableDeclarationList(data));
  }
}
