// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// @docImport 'dart:ui';
///
/// @docImport 'package:flutter/material.dart';
/// @docImport 'package:flutter/rendering.dart';
/// @docImport 'package:flutter_test/flutter_test.dart';
library;

import 'dart:core';
import 'dart:math' as math;
import 'dart:ui'
    show
        CheckedState,
        Locale,
        Offset,
        Rect,
        SemanticsAction,
        SemanticsFlag,
        SemanticsFlags,
        SemanticsInputType,
        SemanticsRole,
        SemanticsUpdate,
        SemanticsUpdateBuilder,
        SemanticsValidationResult,
        StringAttribute,
        TextDirection,
        Tristate;
import 'dart:ui' as ui show SemanticsHitTestBehavior;

import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart' show MatrixUtils, TransformProperty;
import 'package:flutter/services.dart';
import 'package:vector_math/vector_math_64.dart';

import 'binding.dart' show SemanticsBinding;
import 'semantics_event.dart';

export 'dart:ui'
    show
        Offset,
        Rect,
        SemanticsAction,
        SemanticsFlag,
        SemanticsFlags,
        SemanticsRole,
        SemanticsValidationResult,
        StringAttribute,
        TextDirection,
        VoidCallback;

export 'package:flutter/foundation.dart'
    show
        DiagnosticLevel,
        DiagnosticPropertiesBuilder,
        DiagnosticsNode,
        DiagnosticsTreeStyle,
        Key,
        TextTreeConfiguration;
export 'package:flutter/services.dart' show TextSelection;
export 'package:vector_math/vector_math_64.dart' show Matrix4;

export 'semantics_event.dart' show SemanticsEvent;

/// Signature for a function that is called for each [SemanticsNode].
///
/// Return false to stop visiting nodes.
///
/// Used by [SemanticsNode.visitChildren].
typedef SemanticsNodeVisitor = bool Function(SemanticsNode node);

/// Signature for [SemanticsAction]s that move the cursor.
///
/// If `extendSelection` is set to true the cursor movement should extend the
/// current selection or (if nothing is currently selected) start a selection.
typedef MoveCursorHandler = void Function(bool extendSelection);

/// Signature for the [SemanticsAction.setSelection] handlers to change the
/// text selection (or re-position the cursor) to `selection`.
typedef SetSelectionHandler = void Function(TextSelection selection);

/// Signature for the [SemanticsAction.setText] handlers to replace the
/// current text with the input `text`.
typedef SetTextHandler = void Function(String text);

/// Signature for the [SemanticsAction.scrollToOffset] handlers to scroll the
/// scrollable container to the given `targetOffset`.
typedef ScrollToOffsetHandler = void Function(Offset targetOffset);

/// Signature for a handler of a [SemanticsAction].
///
/// Returned by [SemanticsConfiguration.getActionHandler].
typedef SemanticsActionHandler = void Function(Object? args);

/// Signature for a function that receives a semantics update and returns no result.
///
/// Used by [SemanticsOwner.onSemanticsUpdate].
typedef SemanticsUpdateCallback = void Function(SemanticsUpdate update);

/// Signature for the [SemanticsConfiguration.childConfigurationsDelegate].
///
/// The input list contains all [SemanticsConfiguration]s that rendering
/// children want to merge upward. One can tag a render child with a
/// [SemanticsTag] and look up its [SemanticsConfiguration]s through
/// [SemanticsConfiguration.tagsChildrenWith].
///
/// The return value is the arrangement of these configs, including which
/// configs continue to merge upward and which configs form sibling merge group.
///
/// Use [ChildSemanticsConfigurationsResultBuilder] to generate the return
/// value.
typedef ChildSemanticsConfigurationsDelegate =
    ChildSemanticsConfigurationsResult Function(List<SemanticsConfiguration>);

/// Controls how accessibility focus is blocked.
///
/// This is typically used to prevent screen readers
/// from focusing on parts of the UI.
enum AccessibilityFocusBlockType {
  /// Accessibility focus is **not blocked**.
  none,

  /// Blocks accessibility focus for the entire subtree.
  blockSubtree,

  /// Blocks accessibility focus for the **current node only**. Its descendants
  /// may still be focusable.
  blockNode;

  /// The AccessibilityFocusBlockType when two nodes get merged.
  AccessibilityFocusBlockType _merge(AccessibilityFocusBlockType other) {
    // 1. If either is blockSubtree, the result is blockSubtree.
    if (this == AccessibilityFocusBlockType.blockSubtree ||
        other == AccessibilityFocusBlockType.blockSubtree) {
      return AccessibilityFocusBlockType.blockSubtree;
    }

    // 2. If either is blockNode, the result is blockNode
    if (this == AccessibilityFocusBlockType.blockNode ||
        other == AccessibilityFocusBlockType.blockNode) {
      return AccessibilityFocusBlockType.blockNode;
    }

    // 3. If neither is blockSubtree nor blockNode, both must be none.
    return AccessibilityFocusBlockType.none;
  }
}

final int _kUnblockedUserActions =
    SemanticsAction.didGainAccessibilityFocus.index |
    SemanticsAction.didLoseAccessibilityFocus.index;

/// A static class to conduct semantics role checks.
sealed class _DebugSemanticsRoleChecks {
  static FlutterError? _checkSemanticsData(SemanticsNode node) {
    final FlutterError? error = switch (node.role) {
      SemanticsRole.alertDialog => _noCheckRequired,
      SemanticsRole.dialog => _noCheckRequired,
      SemanticsRole.none => _noCheckRequired,
      SemanticsRole.tab => _semanticsTab,
      SemanticsRole.tabBar => _semanticsTabBar,
      SemanticsRole.tabPanel => _noCheckRequired,
      SemanticsRole.table => _semanticsTable,
      SemanticsRole.cell => _semanticsCell,
      SemanticsRole.row => _semanticsRow,
      SemanticsRole.columnHeader => _semanticsColumnHeader,
      SemanticsRole.radioGroup => _semanticsRadioGroup,
      SemanticsRole.menu => _semanticsMenu,
      SemanticsRole.menuBar => _semanticsMenuBar,
      SemanticsRole.menuItem => _semanticsMenuItem,
      SemanticsRole.menuItemCheckbox => _semanticsMenuItemCheckbox,
      SemanticsRole.menuItemRadio => _semanticsMenuItemRadio,
      SemanticsRole.alert => _noLiveRegion,
      SemanticsRole.status => _noLiveRegion,
      SemanticsRole.list => _noCheckRequired,
      SemanticsRole.listItem => _semanticsListItem,
      SemanticsRole.complementary => _semanticsComplementary,
      SemanticsRole.contentInfo => _semanticsContentInfo,
      SemanticsRole.main => _semanticsMain,
      SemanticsRole.navigation => _semanticsNavigation,
      SemanticsRole.region => _semanticsRegion,
      SemanticsRole.form => _noCheckRequired,
      SemanticsRole.loadingSpinner => _noCheckRequired,
      SemanticsRole.progressBar => _semanticsProgressBar,
      // TODO(chunhtai): add checks when the roles are used in framework.
      // https://github.com/flutter/flutter/issues/159741.
      SemanticsRole.dragHandle => _unimplemented,
      SemanticsRole.spinButton => _unimplemented,
      SemanticsRole.comboBox => _unimplemented,
      SemanticsRole.tooltip => _unimplemented,
      SemanticsRole.hotKey => _unimplemented,
    }(node);

    if (error != null) {
      return error;
    }

    return _semanticsGeneral(node);
  }

  static FlutterError? _unimplemented(SemanticsNode node) =>
      FlutterError('Missing checks for role ${node.getSemanticsData().role}');

  static FlutterError? _noCheckRequired(SemanticsNode node) => null;

  static FlutterError? _semanticsProgressBar(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();

    // Check if value is present
    if (data.value.isEmpty) {
      return FlutterError('A progress bar must have a value');
    }

    // Check if minValue and maxValue are present
    if (data.minValue?.isEmpty ?? true) {
      return FlutterError('A progress bar must have a minValue');
    }

    if (data.maxValue?.isEmpty ?? true) {
      return FlutterError('A progress bar must have a maxValue');
    }

    // Validate that value is within min and max range
    try {
      final double currentValue = double.parse(data.value);
      final double minVal = double.parse(data.minValue!);
      final double maxVal = double.parse(data.maxValue!);

      if (currentValue < minVal || currentValue > maxVal) {
        return FlutterError(
          'Progress bar value ($currentValue) must be between minValue ($minVal) and maxValue ($maxVal)',
        );
      }

      if (minVal >= maxVal) {
        return FlutterError('Progress bar minValue ($minVal) must be less than maxValue ($maxVal)');
      }
    } catch (e) {
      return FlutterError(
        'Progress bar value, minValue, and maxValue must be valid numbers. '
        'value: "${data.value}", minValue: "${data.minValue}", maxValue: "${data.maxValue}"',
      );
    }

    return null;
  }

  static FlutterError? _semanticsTab(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    if (data.flagsCollection.isSelected == Tristate.none) {
      return FlutterError('A tab needs selected states');
    }

    if (node.areUserActionsBlocked) {
      return null;
    }

    if (data.flagsCollection.isEnabled != Tristate.isFalse &&
        !data.hasAction(SemanticsAction.tap)) {
      return FlutterError('A tab must have a tap action');
    }

    return null;
  }

  static FlutterError? _semanticsTabBar(SemanticsNode node) {
    if (node.childrenCount < 1) {
      return FlutterError('a TabBar cannot be empty');
    }
    FlutterError? error;
    node.visitChildren((SemanticsNode child) {
      if (child.getSemanticsData().role != SemanticsRole.tab) {
        error = FlutterError('Children of TabBar must have the tab role');
      }
      return error == null;
    });
    return error;
  }

  static FlutterError? _semanticsTable(SemanticsNode node) {
    FlutterError? error;
    node.visitChildren((SemanticsNode child) {
      if (child.getSemanticsData().role != SemanticsRole.row) {
        error = FlutterError('Children of Table must have the row role');
      }
      return error == null;
    });
    return error;
  }

  static FlutterError? _semanticsRow(SemanticsNode node) {
    if (node.parent?.role != SemanticsRole.table) {
      return FlutterError('A row must be a child of a table');
    }
    FlutterError? error;
    node.visitChildren((SemanticsNode child) {
      if (child.getSemanticsData().role != SemanticsRole.cell &&
          child.getSemanticsData().role != SemanticsRole.columnHeader) {
        error = FlutterError('Children of Row must have the cell or columnHeader role');
      }
      return error == null;
    });
    return error;
  }

  static FlutterError? _semanticsCell(SemanticsNode node) {
    if (node.parent?.role != SemanticsRole.row && node.parent?.role != SemanticsRole.cell) {
      return FlutterError('A cell must be a child of a row or another cell');
    }
    return null;
  }

  static FlutterError? _semanticsColumnHeader(SemanticsNode node) {
    if (node.parent?.role != SemanticsRole.row && node.parent?.role != SemanticsRole.cell) {
      return FlutterError('A columnHeader must be a child or another cell');
    }
    return null;
  }

  static FlutterError? _semanticsRadioGroup(SemanticsNode node) {
    FlutterError? error;
    var hasCheckedChild = false;
    bool validateRadioGroupChildren(SemanticsNode node) {
      final SemanticsData data = node.getSemanticsData();
      if (data.role == SemanticsRole.radioGroup) {
        // Children under sub radio groups don't belong to this radio group.
        return error == null;
      }

      if (!data.flagsCollection.isInMutuallyExclusiveGroup) {
        node.visitChildren(validateRadioGroupChildren);
        return error == null;
      }

      if (data.flagsCollection.isChecked == CheckedState.isTrue) {
        if (hasCheckedChild) {
          error = FlutterError('Radio groups must not have multiple checked children');
          return false;
        }
        hasCheckedChild = true;
      }

      assert(error == null);
      return true;
    }

    node.visitChildren(validateRadioGroupChildren);
    return error;
  }

  static FlutterError? _semanticsMenu(SemanticsNode node) {
    if (node.childrenCount < 1) {
      return FlutterError('a menu cannot be empty');
    }

    return null;
  }

  static FlutterError? _semanticsMenuBar(SemanticsNode node) {
    if (node.childrenCount < 1) {
      return FlutterError('a menu bar cannot be empty');
    }

    return null;
  }

  static FlutterError? _semanticsMenuItem(SemanticsNode node) {
    SemanticsNode? currentNode = node;
    while (currentNode?.parent != null) {
      if (currentNode?.parent?.role == SemanticsRole.menu ||
          currentNode?.parent?.role == SemanticsRole.menuBar) {
        return null;
      }
      currentNode = currentNode?.parent;
    }
    return FlutterError('A menu item must be a child of a menu or a menu bar');
  }

  static FlutterError? _semanticsMenuItemCheckbox(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    if (data.flagsCollection.isChecked == CheckedState.none) {
      return FlutterError('a menu item checkbox must be checkable');
    }

    SemanticsNode? currentNode = node;
    while (currentNode?.parent != null) {
      if (currentNode?.parent?.role == SemanticsRole.menu ||
          currentNode?.parent?.role == SemanticsRole.menuBar) {
        return null;
      }
      currentNode = currentNode?.parent;
    }
    return FlutterError('A menu item checkbox must be a child of a menu or a menu bar');
  }

  static FlutterError? _semanticsMenuItemRadio(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    if (data.flagsCollection.isChecked == CheckedState.none) {
      return FlutterError('a menu item radio must be checkable');
    }

    SemanticsNode? currentNode = node;
    while (currentNode?.parent != null) {
      if (currentNode?.parent?.role == SemanticsRole.menu ||
          currentNode?.parent?.role == SemanticsRole.menuBar) {
        return null;
      }
      currentNode = currentNode?.parent;
    }
    return FlutterError('A menu item radio must be a child of a menu or a menu bar');
  }

  static FlutterError? _noLiveRegion(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    if (data.flagsCollection.isLiveRegion) {
      return FlutterError(
        'Node ${node.id} has role ${data.role} but is also a live region. '
        'A node can not have ${data.role} and be live region at the same time. '
        'Either remove the role or the live region',
      );
    }
    return null;
  }

  static FlutterError? _semanticsListItem(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    final SemanticsNode? parent = node.parent;
    if (parent == null) {
      return FlutterError(
        "Semantics node ${node.id} has role ${data.role} but doesn't have a parent",
      );
    }
    final SemanticsData parentSemanticsData = parent.getSemanticsData();
    if (parentSemanticsData.role != SemanticsRole.list) {
      return FlutterError(
        'Semantics node ${node.id} has role ${data.role}, but its '
        "parent node ${parent.id} doesn't have the role ${SemanticsRole.list}. "
        'Please assign the ${SemanticsRole.list} to node ${parent.id}',
      );
    }
    return null;
  }

  static bool _isLandmarkRole(SemanticsData nodeData) =>
      nodeData.role == SemanticsRole.complementary ||
      nodeData.role == SemanticsRole.contentInfo ||
      nodeData.role == SemanticsRole.main ||
      nodeData.role == SemanticsRole.navigation ||
      nodeData.role == SemanticsRole.region;

  static bool _isSameRoleExisted(SemanticsNode semanticsNode) {
    final Map<int, SemanticsNode> treeNodes = semanticsNode.owner!._nodes;
    var sameRoleCount = 0;
    for (final int id in treeNodes.keys) {
      if (treeNodes[id]?.getSemanticsData().role == semanticsNode.role) {
        sameRoleCount++;
        if (sameRoleCount > 1) {
          return true;
        }
      }
    }
    return false;
  }

  static FlutterError? _semanticsComplementary(SemanticsNode node) {
    SemanticsNode? currentNode = node.parent;
    while (currentNode != null) {
      if (_isLandmarkRole(currentNode.getSemanticsData())) {
        return FlutterError(
          'The complementary landmark role should not contained within any other landmark roles.',
        );
      }
      currentNode = currentNode.parent;
    }

    final SemanticsData data = node.getSemanticsData();
    if (_isSameRoleExisted(node) && data.label.isEmpty) {
      return FlutterError(
        'The complementary landmark role should have a unique label as it is used more than once.',
      );
    }
    return null;
  }

  static FlutterError? _semanticsContentInfo(SemanticsNode node) {
    SemanticsNode? currentNode = node.parent;
    while (currentNode != null) {
      if (_isLandmarkRole(currentNode.getSemanticsData())) {
        return FlutterError(
          'The contentInfo landmark role should not contained within any other landmark roles.',
        );
      }
      currentNode = currentNode.parent;
    }

    final SemanticsData data = node.getSemanticsData();
    if (_isSameRoleExisted(node) && data.label.isEmpty) {
      return FlutterError(
        'The contentInfo landmark role should have a unique label as it is used more than once.',
      );
    }
    return null;
  }

  static FlutterError? _semanticsMain(SemanticsNode node) {
    SemanticsNode? currentNode = node.parent;
    while (currentNode != null) {
      if (_isLandmarkRole(currentNode.getSemanticsData())) {
        return FlutterError(
          'The main landmark role should not contained within any other landmark roles.',
        );
      }
      currentNode = currentNode.parent;
    }

    final SemanticsData data = node.getSemanticsData();
    if (_isSameRoleExisted(node) && data.label.isEmpty) {
      return FlutterError(
        'The main landmark role should have a unique label as it is used more than once.',
      );
    }
    return null;
  }

  static FlutterError? _semanticsNavigation(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    if (_isSameRoleExisted(node) && data.label.isEmpty) {
      return FlutterError(
        'The navigation landmark role should have a unique label as it is used more than once.',
      );
    }
    return null;
  }

  static FlutterError? _semanticsRegion(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    if (data.label.isEmpty) {
      return FlutterError(
        'A region role should include a label that describes the purpose of the content.',
      );
    }

    return null;
  }

  static FlutterError? _semanticsGeneral(SemanticsNode node) {
    final SemanticsData data = node.getSemanticsData();
    final bool? isExpanded = data.flagsCollection.isExpanded.toBoolOrNull();

    if (isExpanded != null) {
      final bool hasExpandAction = data.hasAction(SemanticsAction.expand);
      final bool hasCollapseAction = data.hasAction(SemanticsAction.collapse);

      if (hasExpandAction && hasCollapseAction) {
        return FlutterError(
          'An expandable node cannot have both expand and collapse actions set at the same time.',
        );
      }
      if (isExpanded && hasExpandAction) {
        return FlutterError('An expanded node cannot have an expand action.');
      }
      if (!isExpanded && hasCollapseAction) {
        return FlutterError('A collapsed node cannot have a collapse action.');
      }
    }
    if (data.flagsCollection.isAccessibilityFocusBlocked &&
        data.flagsCollection.isFocused != Tristate.none) {
      return FlutterError(
        'A node that is keyboard focusable cannot be set to accessibility unfocusable',
      );
    }

    return null;
  }
}

/// A tag for a [SemanticsNode].
///
/// Tags can be interpreted by the parent of a [SemanticsNode]
/// and depending on the presence of a tag the parent can for example decide
/// how to add the tagged node as a child. Tags are not sent to the engine.
///
/// As an example, the [RenderSemanticsGestureHandler] uses tags to determine
/// if a child node should be excluded from the scrollable area for semantic
/// purposes.
///
/// The provided [name] is only used for debugging. Two tags created with the
/// same [name] and the `new` operator are not considered identical. However,
/// two tags created with the same [name] and the `const` operator are always
/// identical.
class SemanticsTag {
  /// Creates a [SemanticsTag].
  ///
  /// The provided [name] is only used for debugging. Two tags created with the
  /// same [name] and the `new` operator are not considered identical. However,
  /// two tags created with the same [name] and the `const` operator are always
  /// identical.
  const SemanticsTag(this.name);

  /// A human-readable name for this tag used for debugging.
  ///
  /// This string is not used to determine if two tags are identical.
  final String name;

  @override
  String toString() => '${objectRuntimeType(this, 'SemanticsTag')}($name)';
}

/// The result that contains the arrangement for the child
/// [SemanticsConfiguration]s.
///
/// When the [PipelineOwner] builds the semantics tree, it uses the returned
/// [ChildSemanticsConfigurationsResult] from
/// [SemanticsConfiguration.childConfigurationsDelegate] to decide how semantics nodes
/// should form.
///
/// Use [ChildSemanticsConfigurationsResultBuilder] to build the result.
class ChildSemanticsConfigurationsResult {
  ChildSemanticsConfigurationsResult._(this.mergeUp, this.siblingMergeGroups);

  /// Returns the [SemanticsConfiguration]s that are supposed to be merged into
  /// the parent semantics node.
  ///
  /// [SemanticsConfiguration]s that are either semantics boundaries or are
  /// conflicting with other [SemanticsConfiguration]s will form explicit
  /// semantics nodes. All others will be merged into the parent.
  final List<SemanticsConfiguration> mergeUp;

  /// The groups of child semantics configurations that want to merge together
  /// and form a sibling [SemanticsNode].
  ///
  /// All the [SemanticsConfiguration]s in a given group that are either
  /// semantics boundaries or are conflicting with other
  /// [SemanticsConfiguration]s of the same group will be excluded from the
  /// sibling merge group and form independent semantics nodes as usual.
  ///
  /// The result [SemanticsNode]s from the merges are attached as the sibling
  /// nodes of the immediate parent semantics node. For example, a `RenderObjectA`
  /// has a rendering child, `RenderObjectB`. If both of them form their own
  /// semantics nodes, `SemanticsNodeA` and `SemanticsNodeB`, any semantics node
  /// created from sibling merge groups of `RenderObjectB` will be attach to
  /// `SemanticsNodeA` as a sibling of `SemanticsNodeB`.
  final List<List<SemanticsConfiguration>> siblingMergeGroups;
}

/// The builder to build a [ChildSemanticsConfigurationsResult] based on its
/// annotations.
///
/// To use this builder, one can use [markAsMergeUp] and
/// [markAsSiblingMergeGroup] to annotate the arrangement of
/// [SemanticsConfiguration]s. Once all the configs are annotated, use [build]
/// to generate the [ChildSemanticsConfigurationsResult].
class ChildSemanticsConfigurationsResultBuilder {
  /// Creates a [ChildSemanticsConfigurationsResultBuilder].
  ChildSemanticsConfigurationsResultBuilder();

  final List<SemanticsConfiguration> _mergeUp = <SemanticsConfiguration>[];
  final List<List<SemanticsConfiguration>> _siblingMergeGroups = <List<SemanticsConfiguration>>[];

  /// Marks the [SemanticsConfiguration] to be merged into the parent semantics
  /// node.
  ///
  /// The [SemanticsConfiguration] will be added to the
  /// [ChildSemanticsConfigurationsResult.mergeUp] that this builder builds.
  void markAsMergeUp(SemanticsConfiguration config) => _mergeUp.add(config);

  /// Marks a group of [SemanticsConfiguration]s to merge together
  /// and form a sibling [SemanticsNode].
  ///
  /// The group of [SemanticsConfiguration]s will be added to the
  /// [ChildSemanticsConfigurationsResult.siblingMergeGroups] that this builder builds.
  void markAsSiblingMergeGroup(List<SemanticsConfiguration> configs) =>
      _siblingMergeGroups.add(configs);

  /// Builds a [ChildSemanticsConfigurationsResult] contains the arrangement.
  ChildSemanticsConfigurationsResult build() {
    assert(() {
      final seenConfigs = <SemanticsConfiguration>{};
      for (final config in <SemanticsConfiguration>[
        ..._mergeUp,
        ..._siblingMergeGroups.flattened,
      ]) {
        assert(
          seenConfigs.add(config),
          'Duplicated SemanticsConfigurations. This can happen if the same '
          'SemanticsConfiguration was marked twice in markAsMergeUp and/or '
          'markAsSiblingMergeGroup',
        );
      }
      return true;
    }());
    return ChildSemanticsConfigurationsResult._(_mergeUp, _siblingMergeGroups);
  }
}

/// An identifier of a custom semantics action.
///
/// Custom semantics actions can be provided to make complex user
/// interactions more accessible. For instance, if an application has a
/// drag-and-drop list that requires the user to press and hold an item
/// to move it, users interacting with the application using a hardware
/// switch may have difficulty. This can be made accessible by creating custom
/// actions and pairing them with handlers that move a list item up or down in
/// the list.
///
/// In Android, these actions are presented in the local context menu. In iOS,
/// these are presented in the radial context menu.
///
/// Localization and text direction do not automatically apply to the provided
/// label or hint.
///
/// Instances of this class should either be instantiated with const or
/// new instances cached in static fields.
///
/// See also:
///
///  * [SemanticsProperties], where the handler for a custom action is provided.
@immutable
class CustomSemanticsAction {
  /// Creates a new [CustomSemanticsAction].
  ///
  /// The [label] must not be empty.
  const CustomSemanticsAction({required String this.label})
    : assert(label != ''),
      hint = null,
      action = null;

  /// Creates a new [CustomSemanticsAction] that overrides a standard semantics
  /// action.
  ///
  /// The [hint] must not be empty.
  const CustomSemanticsAction.overridingAction({
    required String this.hint,
    required SemanticsAction this.action,
  }) : assert(hint != ''),
       label = null;

  /// The user readable name of this custom semantics action.
  final String? label;

  /// The hint description of this custom semantics action.
  final String? hint;

  /// The standard semantics action this action replaces.
  final SemanticsAction? action;

  @override
  int get hashCode => Object.hash(label, hint, action);

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is CustomSemanticsAction &&
        other.label == label &&
        other.hint == hint &&
        other.action == action;
  }

  @override
  String toString() {
    return 'CustomSemanticsAction(${_ids[this]}, label:$label, hint:$hint, action:$action)';
  }

  // Logic to assign a unique id to each custom action without requiring
  // user specification.
  static int _nextId = 0;
  static final Map<int, CustomSemanticsAction> _actions = <int, CustomSemanticsAction>{};
  static final Map<CustomSemanticsAction, int> _ids = <CustomSemanticsAction, int>{};

  /// Get the identifier for a given `action`.
  static int getIdentifier(CustomSemanticsAction action) {
    int? result = _ids[action];
    if (result == null) {
      result = _nextId++;
      _ids[action] = result;
      _actions[result] = action;
    }
    return result;
  }

  /// Get the `action` for a given identifier.
  static CustomSemanticsAction? getAction(int id) {
    return _actions[id];
  }

  /// Resets internal state between tests. Does nothing if asserts are disabled.
  @visibleForTesting
  static void resetForTests() {
    assert(() {
      _actions.clear();
      _ids.clear();
      _nextId = 0;
      return true;
    }());
  }
}

/// A string that carries a list of [StringAttribute]s.
@immutable
class AttributedString {
  /// Creates a attributed string.
  ///
  /// The [TextRange] in the [attributes] must be inside the length of the
  /// [string].
  ///
  /// The [attributes] must not be changed after the attributed string is
  /// created.
  AttributedString(this.string, {this.attributes = const <StringAttribute>[]})
    : assert(string.isNotEmpty || attributes.isEmpty),
      assert(() {
        for (final attribute in attributes) {
          assert(
            string.length >= attribute.range.start && string.length >= attribute.range.end,
            'The range in $attribute is outside of the string $string',
          );
        }
        return true;
      }());

  /// The plain string stored in the attributed string.
  final String string;

  /// The attributes this string carries.
  ///
  /// The list must not be modified after this string is created.
  final List<StringAttribute> attributes;

  /// Returns a new [AttributedString] by concatenate the operands
  ///
  /// The string attribute list of the returned [AttributedString] will contains
  /// the string attributes from both operands with updated text ranges.
  AttributedString operator +(AttributedString other) {
    if (string.isEmpty) {
      return other;
    }
    if (other.string.isEmpty) {
      return this;
    }

    // None of the strings is empty.
    final String newString = string + other.string;
    final newAttributes = List<StringAttribute>.of(attributes);
    if (other.attributes.isNotEmpty) {
      final int offset = string.length;
      for (final StringAttribute attribute in other.attributes) {
        final newRange = TextRange(
          start: attribute.range.start + offset,
          end: attribute.range.end + offset,
        );
        final StringAttribute adjustedAttribute = attribute.copy(range: newRange);
        newAttributes.add(adjustedAttribute);
      }
    }
    return AttributedString(newString, attributes: newAttributes);
  }

  /// Two [AttributedString]s are equal if their string and attributes are.
  @override
  bool operator ==(Object other) {
    return other.runtimeType == runtimeType &&
        other is AttributedString &&
        other.string == string &&
        listEquals<StringAttribute>(other.attributes, attributes);
  }

  @override
  int get hashCode => Object.hash(string, attributes);

  @override
  String toString() {
    return "${objectRuntimeType(this, 'AttributedString')}('$string', attributes: $attributes)";
  }
}

/// A [DiagnosticsProperty] for [AttributedString]s, which shows a string
/// when there are no attributes, and more details otherwise.
class AttributedStringProperty extends DiagnosticsProperty<AttributedString> {
  /// Create a diagnostics property for an [AttributedString] object.
  ///
  /// Such properties are used with [SemanticsData] objects.
  AttributedStringProperty(
    String super.name,
    super.value, {
    super.showName,
    this.showWhenEmpty = false,
    super.defaultValue,
    super.level,
    super.description,
  });

  /// Whether to show the property when the [value] is an [AttributedString]
  /// whose [AttributedString.string] is the empty string.
  ///
  /// This overrides [defaultValue].
  final bool showWhenEmpty;

  @override
  bool get isInteresting =>
      super.isInteresting && (showWhenEmpty || (value != null && value!.string.isNotEmpty));

  @override
  String valueToString({TextTreeConfiguration? parentConfiguration}) {
    if (value == null) {
      return 'null';
    }
    String text = value!.string;
    if (parentConfiguration != null && !parentConfiguration.lineBreakProperties) {
      // This follows a similar pattern to StringProperty.
      text = text.replaceAll('\n', r'\n');
    }
    if (value!.attributes.isEmpty) {
      return '"$text"';
    }
    return '"$text" ${value!.attributes}'; // the attributes will be in square brackets since they're a list
  }
}

typedef _LabelPart = (String text, TextDirection? textDirection);

/// Builder for creating semantically correct concatenated labels with proper
/// text direction handling and spacing.
///
/// This builder helps address the complexity of concatenating multiple text
/// parts while handling language-specific nuances like RTL vs LTR text direction
/// and proper spacing.
///
/// Example usage:
/// ```dart
/// SemanticsLabelBuilder builder = SemanticsLabelBuilder()
///   ..addPart('Hello')
///   ..addPart('world');
/// String label = builder.build(); // "Hello world"
/// ```
///
/// For multilingual text with proper RTL support:
/// ```dart
/// SemanticsLabelBuilder builder = SemanticsLabelBuilder(textDirection: TextDirection.ltr)
///   ..addPart('Welcome', textDirection: TextDirection.ltr)
///   ..addPart('مرحبا', textDirection: TextDirection.rtl); // Arabic
/// String label = builder.build(); // "Welcome \u202Bمرحبا\u202C" (with Unicode embedding)
/// ```
final class SemanticsLabelBuilder {
  /// Creates a new [SemanticsLabelBuilder].
  ///
  /// The [separator] is used between text parts (defaults to space).
  /// The [textDirection] specifies the overall text direction for the concatenated label.
  SemanticsLabelBuilder({this.separator = ' ', this.textDirection});

  /// The separator used between text parts.
  final String separator;

  /// The overall text direction for the concatenated label.
  final TextDirection? textDirection;

  final List<_LabelPart> _parts = <_LabelPart>[];

  /// Adds a text part.
  ///
  /// If [textDirection] is specified, it will be used for this specific part.
  /// Empty parts are ignored.
  void addPart(String label, {TextDirection? textDirection}) {
    if (label.isNotEmpty) {
      _parts.add((label, textDirection));
    }
  }

  /// Returns true if no parts have been added to this builder.
  bool get isEmpty => _parts.isEmpty;

  /// Returns the number of parts added to this builder.
  int get length => _parts.length;

  /// Builds and returns the concatenated label from the added parts.
  ///
  /// This method concatenates all parts with proper text direction handling
  /// and spacing.
  String build() {
    if (_parts.isEmpty) {
      return '';
    }

    if (_parts.length == 1) {
      final (String text, TextDirection? _) = _parts.first;
      return text;
    }

    // Concatenate multiple parts with proper text direction handling
    final buffer = StringBuffer();
    final (String firstText, TextDirection? _) = _parts.first;
    buffer.write(firstText);

    for (final (String partText, TextDirection? partTextDirection) in _parts.skip(1)) {
      final TextDirection? partDirection = partTextDirection ?? textDirection;

      if (separator.isNotEmpty) {
        buffer.write(separator);
      }

      var processedText = partText;
      if (textDirection != null && partDirection != null && textDirection != partDirection) {
        final String directionalEmbedding = switch (partDirection) {
          TextDirection.rtl => Unicode.RLE,
          TextDirection.ltr => Unicode.LRE,
        };
        processedText = directionalEmbedding + partText + Unicode.PDF;
      }

      buffer.write(processedText);
    }

    return buffer.toString();
  }

  /// Clears all parts from this builder, allowing it to be reused.
  void clear() {
    _parts.clear();
  }
}

/// Summary information about a [SemanticsNode] object.
///
/// A semantics node might [SemanticsNode.mergeAllDescendantsIntoThisNode],
/// which means the individual fields on the semantics node don't fully describe
/// the semantics at that node. This data structure contains the full semantics
/// for the node.
///
/// Typically obtained from [SemanticsNode.getSemanticsData].
@immutable
class SemanticsData with Diagnosticable {
  /// Creates a semantics data object.
  ///
  /// If [label] is not empty, then [textDirection] must also not be null.
  SemanticsData({
    required this.flagsCollection,
    required this.actions,
    required this.identifier,
    required this.traversalParentIdentifier,
    required this.traversalChildIdentifier,
    required this.attributedLabel,
    required this.attributedValue,
    required this.attributedIncreasedValue,
    required this.attributedDecreasedValue,
    required this.attributedHint,
    required this.tooltip,
    required this.textDirection,
    required this.rect,
    required this.textSelection,
    required this.scrollIndex,
    required this.scrollChildCount,
    required this.scrollPosition,
    required this.scrollExtentMax,
    required this.scrollExtentMin,
    required this.platformViewId,
    required this.maxValueLength,
    required this.currentValueLength,
    required this.headingLevel,
    required this.linkUrl,
    required this.role,
    required this.controlsNodes,
    required this.validationResult,
    required this.hitTestBehavior,
    required this.inputType,
    required this.locale,
    required this.minValue,
    required this.maxValue,
    this.tags,
    this.transform,
    this.customSemanticsActionIds,
  }) : assert(
         tooltip == '' || textDirection != null,
         'A SemanticsData object with tooltip "$tooltip" had a null textDirection.',
       ),
       assert(
         attributedLabel.string == '' || textDirection != null,
         'A SemanticsData object with label "${attributedLabel.string}" had a null textDirection.',
       ),
       assert(
         attributedValue.string == '' || textDirection != null,
         'A SemanticsData object with value "${attributedValue.string}" had a null textDirection.',
       ),
       assert(
         attributedDecreasedValue.string == '' || textDirection != null,
         'A SemanticsData object with decreasedValue "${attributedDecreasedValue.string}" had a null textDirection.',
       ),
       assert(
         attributedIncreasedValue.string == '' || textDirection != null,
         'A SemanticsData object with increasedValue "${attributedIncreasedValue.string}" had a null textDirection.',
       ),
       assert(
         attributedHint.string == '' || textDirection != null,
         'A SemanticsData object with hint "${attributedHint.string}" had a null textDirection.',
       ),
       assert(headingLevel >= 0 && headingLevel <= 6, 'Heading level must be between 0 and 6'),
       assert(
         linkUrl == null || flagsCollection.isLink,
         'A SemanticsData object with a linkUrl must have the isLink flag set to true',
       );

  /// A bit field of [SemanticsFlag]s that apply to this node.
  @Deprecated(
    'Use flagsCollection instead. '
    'This feature was deprecated after v3.29.0-0.3.pre.',
  )
  int get flags => _toBitMask(flagsCollection);

  /// Semantics flags.
  final SemanticsFlags flagsCollection;

  /// A bit field of [SemanticsAction]s that apply to this node.
  final int actions;

  /// {@macro flutter.semantics.SemanticsProperties.identifier}
  final String identifier;

  /// {@macro flutter.semantics.SemanticsProperties.traversalParentIdentifier}
  final Object? traversalParentIdentifier;

  /// {@macro flutter.semantics.SemanticsProperties.traversalChildIdentifier}
  final Object? traversalChildIdentifier;

  /// A textual description for the current label of the node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedLabel].
  String get label => attributedLabel.string;

  /// A textual description for the current label of the node in
  /// [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [label], which exposes just the raw text.
  final AttributedString attributedLabel;

  /// A textual description for the current value of the node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedValue].
  String get value => attributedValue.string;

  /// A textual description for the current value of the node in
  /// [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [value], which exposes just the raw text.
  final AttributedString attributedValue;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.increase] action.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedIncreasedValue].
  String get increasedValue => attributedIncreasedValue.string;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.increase] action in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [increasedValue], which exposes just the raw text.
  final AttributedString attributedIncreasedValue;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.decrease] action.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedDecreasedValue].
  String get decreasedValue => attributedDecreasedValue.string;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.decrease] action in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [decreasedValue], which exposes just the raw text.
  final AttributedString attributedDecreasedValue;

  /// A brief description of the result of performing an action on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedHint].
  String get hint => attributedHint.string;

  /// A brief description of the result of performing an action on this node
  /// in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [hint], which exposes just the raw text.
  final AttributedString attributedHint;

  /// A textual description of the widget's tooltip.
  ///
  /// The reading direction is given by [textDirection].
  final String tooltip;

  /// Indicates that this subtree represents a heading.
  ///
  /// A value of 0 indicates that it is not a heading. The value should be a
  /// number between 1 and 6, indicating the hierarchical level as a heading.
  final int headingLevel;

  /// The reading direction for the text in [label], [value],
  /// [increasedValue], [decreasedValue], and [hint].
  final TextDirection? textDirection;

  /// The currently selected text (or the position of the cursor) within [value]
  /// if this node represents a text field.
  final TextSelection? textSelection;

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  final int? scrollChildCount;

  /// The index of the first visible semantic child of a scroll node.
  final int? scrollIndex;

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  final double? scrollPosition;

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  final double? scrollExtentMax;

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent], from where this value is usually taken.
  final double? scrollExtentMin;

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  ///
  /// If this value is non-null, the SemanticsNode must not have any children
  /// as those would be replaced by the semantics nodes of the referenced
  /// platform view.
  ///
  /// See also:
  ///
  ///  * [AndroidView], which is the platform view for Android.
  ///  * [UiKitView], which is the platform view for iOS.
  final int? platformViewId;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
  /// to null, which means no limit is imposed on the text field.
  final int? maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. This must
  /// be set when [maxValueLength] is set.
  final int? currentValueLength;

  /// The URL that this node links to.
  ///
  /// See also:
  ///
  /// * [SemanticsFlag.isLink], which indicates that this node is a link.
  final Uri? linkUrl;

  /// The bounding box for this node in its coordinate system.
  final Rect rect;

  /// The set of [SemanticsTag]s associated with this node.
  final Set<SemanticsTag>? tags;

  /// The transform from this node's coordinate system to its parent's coordinate system.
  ///
  /// By default, the transform is null, which represents the identity
  /// transformation (i.e., that this node has the same coordinate system as its
  /// parent).
  final Matrix4? transform;

  /// The identifiers for the custom semantics actions and standard action
  /// overrides for this node.
  ///
  /// The list must be sorted in increasing order.
  ///
  /// See also:
  ///
  ///  * [CustomSemanticsAction], for an explanation of custom actions.
  final List<int>? customSemanticsActionIds;

  /// {@macro flutter.semantics.SemanticsNode.role}
  final SemanticsRole role;

  /// {@macro flutter.semantics.SemanticsNode.controlsNodes}
  ///
  /// {@macro flutter.semantics.SemanticsProperties.controlsNodes}
  final Set<String>? controlsNodes;

  /// {@macro flutter.semantics.SemanticsProperties.validationResult}
  final SemanticsValidationResult validationResult;

  /// {@macro flutter.semantics.SemanticsProperties.hitTestBehavior}
  final ui.SemanticsHitTestBehavior hitTestBehavior;

  /// {@macro flutter.semantics.SemanticsNode.inputType}
  final SemanticsInputType inputType;

  /// The locale for this semantics node.
  ///
  /// Assistive technologies uses this property to correctly interpret the
  /// content of this semantics node.
  final Locale? locale;

  /// {@macro flutter.semantics.SemanticsProperties.maxValue}
  final String? maxValue;

  /// {@macro flutter.semantics.SemanticsProperties.minValue}
  final String? minValue;

  /// Whether [flags] contains the given flag.
  @Deprecated(
    'Use flagsCollection instead. '
    'This feature was deprecated after v3.32.0-0.0.pre.',
  )
  bool hasFlag(SemanticsFlag flag) => (flags & flag.index) != 0;

  /// Whether [actions] contains the given action.
  bool hasAction(SemanticsAction action) => (actions & action.index) != 0;

  @override
  String toStringShort() => objectRuntimeType(this, 'SemanticsData');

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<Rect>('rect', rect, showName: false));
    properties.add(TransformProperty('transform', transform, showName: false, defaultValue: null));
    final actionSummary = <String>[
      for (final SemanticsAction action in SemanticsAction.values)
        if ((actions & action.index) != 0) action.name,
    ];
    final List<String?> customSemanticsActionSummary = customSemanticsActionIds!
        .map<String?>((int actionId) => CustomSemanticsAction.getAction(actionId)!.label)
        .toList();
    properties.add(IterableProperty<String>('actions', actionSummary, ifEmpty: null));
    properties.add(
      IterableProperty<String?>('customActions', customSemanticsActionSummary, ifEmpty: null),
    );

    final List<String> flagSummary = flagsCollection.toStrings();
    properties.add(IterableProperty<String>('flags', flagSummary, ifEmpty: null));
    properties.add(StringProperty('identifier', identifier, defaultValue: ''));
    properties.add(
      DiagnosticsProperty<Object>(
        'traversalParentIdentifier',
        traversalParentIdentifier,
        defaultValue: null,
      ),
    );
    properties.add(
      DiagnosticsProperty<Object>(
        'traversalChildIdentifier',
        traversalChildIdentifier,
        defaultValue: null,
      ),
    );
    properties.add(AttributedStringProperty('label', attributedLabel));
    properties.add(AttributedStringProperty('value', attributedValue));
    properties.add(AttributedStringProperty('increasedValue', attributedIncreasedValue));
    properties.add(AttributedStringProperty('decreasedValue', attributedDecreasedValue));
    properties.add(AttributedStringProperty('hint', attributedHint));
    properties.add(StringProperty('tooltip', tooltip, defaultValue: ''));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
    if (textSelection?.isValid ?? false) {
      properties.add(
        MessageProperty('textSelection', '[${textSelection!.start}, ${textSelection!.end}]'),
      );
    }
    properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
    properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
    properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
    properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
    properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
    properties.add(DoubleProperty('scrollPosition', scrollPosition, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMax', scrollExtentMax, defaultValue: null));
    properties.add(IntProperty('headingLevel', headingLevel, defaultValue: 0));
    properties.add(DiagnosticsProperty<Uri>('linkUrl', linkUrl, defaultValue: null));
    if (controlsNodes != null) {
      properties.add(IterableProperty<String>('controls', controlsNodes, ifEmpty: null));
    }
    if (role != SemanticsRole.none) {
      properties.add(EnumProperty<SemanticsRole>('role', role, defaultValue: SemanticsRole.none));
    }
    if (validationResult != SemanticsValidationResult.none) {
      properties.add(
        EnumProperty<SemanticsValidationResult>(
          'validationResult',
          validationResult,
          defaultValue: SemanticsValidationResult.none,
        ),
      );
    }
    properties.add(StringProperty('minValue', minValue, defaultValue: null));
    properties.add(StringProperty('maxValue', maxValue, defaultValue: null));
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticsData &&
        other.flags == flags &&
        other.actions == actions &&
        other.identifier == identifier &&
        other.traversalParentIdentifier == traversalParentIdentifier &&
        other.traversalChildIdentifier == traversalChildIdentifier &&
        other.attributedLabel == attributedLabel &&
        other.attributedValue == attributedValue &&
        other.attributedIncreasedValue == attributedIncreasedValue &&
        other.attributedDecreasedValue == attributedDecreasedValue &&
        other.attributedHint == attributedHint &&
        other.tooltip == tooltip &&
        other.textDirection == textDirection &&
        other.rect == rect &&
        setEquals(other.tags, tags) &&
        other.scrollChildCount == scrollChildCount &&
        other.scrollIndex == scrollIndex &&
        other.textSelection == textSelection &&
        other.scrollPosition == scrollPosition &&
        other.scrollExtentMax == scrollExtentMax &&
        other.scrollExtentMin == scrollExtentMin &&
        other.platformViewId == platformViewId &&
        other.maxValueLength == maxValueLength &&
        other.currentValueLength == currentValueLength &&
        other.transform == transform &&
        other.headingLevel == headingLevel &&
        other.linkUrl == linkUrl &&
        other.role == role &&
        other.validationResult == validationResult &&
        other.inputType == inputType &&
        other.hitTestBehavior == hitTestBehavior &&
        _sortedListsEqual(other.customSemanticsActionIds, customSemanticsActionIds) &&
        setEquals<String>(controlsNodes, other.controlsNodes) &&
        other.traversalParentIdentifier == traversalParentIdentifier &&
        other.traversalChildIdentifier == traversalChildIdentifier &&
        other.minValue == minValue &&
        other.maxValue == maxValue;
  }

  @override
  int get hashCode => Object.hash(
    flags,
    actions,
    identifier,
    attributedLabel,
    attributedValue,
    attributedIncreasedValue,
    attributedDecreasedValue,
    attributedHint,
    tooltip,
    textDirection,
    rect,
    tags,
    textSelection,
    scrollChildCount,
    scrollIndex,
    scrollPosition,
    scrollExtentMax,
    scrollExtentMin,
    platformViewId,
    Object.hash(
      maxValueLength,
      currentValueLength,
      transform,
      headingLevel,
      linkUrl,
      customSemanticsActionIds == null ? null : Object.hashAll(customSemanticsActionIds!),
      role,
      validationResult,
      controlsNodes == null ? null : Object.hashAll(controlsNodes!),
      inputType,
      hitTestBehavior,
      traversalParentIdentifier,
      traversalChildIdentifier,
      minValue,
      maxValue,
    ),
  );

  static bool _sortedListsEqual(List<int>? left, List<int>? right) {
    if (left == null && right == null) {
      return true;
    }
    if (left != null && right != null) {
      if (left.length != right.length) {
        return false;
      }
      for (var i = 0; i < left.length; i++) {
        if (left[i] != right[i]) {
          return false;
        }
      }
      return true;
    }
    return false;
  }
}

class _SemanticsDiagnosticableNode extends DiagnosticableNode<SemanticsNode> {
  _SemanticsDiagnosticableNode({
    super.name,
    required super.value,
    required super.style,
    required this.childOrder,
  });

  final DebugSemanticsDumpOrder childOrder;

  @override
  List<DiagnosticsNode> getChildren() => value.debugDescribeChildren(childOrder: childOrder);
}

/// Provides hint values which override the default hints on supported
/// platforms.
///
/// On iOS, these values are always ignored.
@immutable
class SemanticsHintOverrides extends DiagnosticableTree {
  /// Creates a semantics hint overrides.
  const SemanticsHintOverrides({this.onTapHint, this.onLongPressHint})
    : assert(onTapHint != ''),
      assert(onLongPressHint != '');

  /// The hint text for a tap action.
  ///
  /// If null, the standard hint is used instead.
  ///
  /// The hint should describe what happens when a tap occurs, not the
  /// manner in which a tap is accomplished.
  ///
  /// Bad: 'Double tap to show movies'.
  /// Good: 'show movies'.
  final String? onTapHint;

  /// The hint text for a long press action.
  ///
  /// If null, the standard hint is used instead.
  ///
  /// The hint should describe what happens when a long press occurs, not
  /// the manner in which the long press is accomplished.
  ///
  /// Bad: 'Double tap and hold to show tooltip'.
  /// Good: 'show tooltip'.
  final String? onLongPressHint;

  /// Whether there are any non-null hint values.
  bool get isNotEmpty => onTapHint != null || onLongPressHint != null;

  @override
  int get hashCode => Object.hash(onTapHint, onLongPressHint);

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is SemanticsHintOverrides &&
        other.onTapHint == onTapHint &&
        other.onLongPressHint == onLongPressHint;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('onTapHint', onTapHint, defaultValue: null));
    properties.add(StringProperty('onLongPressHint', onLongPressHint, defaultValue: null));
  }
}

/// Contains properties used by assistive technologies to make the application
/// more accessible.
///
/// The properties of this class are used to generate a [SemanticsNode]s in the
/// semantics tree.
@immutable
class SemanticsProperties extends DiagnosticableTree {
  /// Creates a semantic annotation.
  const SemanticsProperties({
    this.enabled,
    this.checked,
    this.mixed,
    this.expanded,
    this.selected,
    this.toggled,
    this.button,
    this.link,
    this.linkUrl,
    this.header,
    this.headingLevel,
    this.textField,
    this.slider,
    this.keyboardKey,
    this.readOnly,
    @Deprecated(
      'Use focused instead. '
      'Setting focused automatically set focusable. '
      'This feature was deprecated after v3.36.0-0.0.pre.',
    )
    this.focusable,
    this.focused,
    this.accessibilityFocusBlockType,
    this.inMutuallyExclusiveGroup,
    this.hidden,
    this.obscured,
    this.multiline,
    this.scopesRoute,
    this.namesRoute,
    this.image,
    this.liveRegion,
    this.isRequired,
    this.maxValueLength,
    this.currentValueLength,
    this.identifier,
    this.traversalParentIdentifier,
    this.traversalChildIdentifier,
    this.label,
    this.attributedLabel,
    this.value,
    this.attributedValue,
    this.increasedValue,
    this.attributedIncreasedValue,
    this.decreasedValue,
    this.attributedDecreasedValue,
    this.hint,
    this.tooltip,
    this.attributedHint,
    this.hintOverrides,
    this.textDirection,
    this.sortKey,
    this.tagForChildren,
    this.role,
    this.controlsNodes,
    this.inputType,
    this.validationResult = SemanticsValidationResult.none,
    this.hitTestBehavior,
    this.onTap,
    this.onLongPress,
    this.onScrollLeft,
    this.onScrollRight,
    this.onScrollUp,
    this.onScrollDown,
    this.onIncrease,
    this.onDecrease,
    this.onCopy,
    this.onCut,
    this.onPaste,
    this.onMoveCursorForwardByCharacter,
    this.onMoveCursorBackwardByCharacter,
    this.onMoveCursorForwardByWord,
    this.onMoveCursorBackwardByWord,
    this.onSetSelection,
    this.onSetText,
    this.onDidGainAccessibilityFocus,
    this.onDidLoseAccessibilityFocus,
    this.onFocus,
    this.onDismiss,
    this.onExpand,
    this.onCollapse,
    this.customSemanticsActions,
    this.minValue,
    this.maxValue,
  }) : assert(
         label == null || attributedLabel == null,
         'Only one of label or attributedLabel should be provided',
       ),
       assert(
         value == null || attributedValue == null,
         'Only one of value or attributedValue should be provided',
       ),
       assert(
         increasedValue == null || attributedIncreasedValue == null,
         'Only one of increasedValue or attributedIncreasedValue should be provided',
       ),
       assert(
         decreasedValue == null || attributedDecreasedValue == null,
         'Only one of decreasedValue or attributedDecreasedValue should be provided',
       ),
       assert(
         hint == null || attributedHint == null,
         'Only one of hint or attributedHint should be provided',
       ),
       assert(
         headingLevel == null || (headingLevel > 0 && headingLevel <= 6),
         'Heading level must be between 1 and 6',
       ),
       assert(linkUrl == null || (link ?? false), 'If linkUrl is set then link must be true');

  /// If non-null, indicates that this subtree represents something that can be
  /// in an enabled or disabled state.
  ///
  /// For example, a button that a user can currently interact with would set
  /// this field to true. A button that currently does not respond to user
  /// interactions would set this field to false.
  final bool? enabled;

  /// If non-null, indicates that this subtree represents a checkbox
  /// or similar widget with a "checked" state, and what its current
  /// state is.
  ///
  /// When the [Checkbox.value] of a tristate Checkbox is null,
  /// indicating a mixed-state, this value shall be false, in which
  /// case, [mixed] will be true.
  ///
  /// This is mutually exclusive with [toggled] and [mixed].
  final bool? checked;

  /// If non-null, indicates that this subtree represents a checkbox
  /// or similar widget with a "half-checked" state or similar, and
  /// whether it is currently in this half-checked state.
  ///
  /// This must be null when [Checkbox.tristate] is false, or
  /// when the widget is not a checkbox. When a tristate
  /// checkbox is fully unchecked/checked, this value shall
  /// be false.
  ///
  /// This is mutually exclusive with [checked] and [toggled].
  final bool? mixed;

  /// If non-null, indicates that this subtree represents something
  /// that can be in an "expanded" or "collapsed" state.
  ///
  /// For example, if a [SubmenuButton] is opened, this property
  /// should be set to true; otherwise, this property should be
  /// false.
  final bool? expanded;

  /// If non-null, indicates that this subtree represents a toggle switch
  /// or similar widget with an "on" state, and what its current
  /// state is.
  ///
  /// This is mutually exclusive with [checked] and [mixed].
  final bool? toggled;

  /// If non-null indicates that this subtree represents something that can be
  /// in a selected or unselected state, and what its current state is.
  ///
  /// The active tab in a tab bar for example is considered "selected", whereas
  /// all other tabs are unselected.
  final bool? selected;

  /// If non-null, indicates that this subtree represents a button.
  ///
  /// TalkBack/VoiceOver provides users with the hint "button" when a button
  /// is focused.
  final bool? button;

  /// If non-null, indicates that this subtree represents a link.
  ///
  /// iOS's VoiceOver provides users with a unique hint when a link is focused.
  /// Android's Talkback will announce a link hint the same way it does a
  /// button.
  final bool? link;

  /// If non-null, indicates that this subtree represents a header.
  ///
  /// A header divides into sections. For example, an address book application
  /// might define headers A, B, C, etc. to divide the list of alphabetically
  /// sorted contacts into sections.
  final bool? header;

  /// If non-null, indicates that this subtree represents a text field.
  ///
  /// TalkBack/VoiceOver provide special affordances to enter text into a
  /// text field.
  final bool? textField;

  /// If non-null, indicates that this subtree represents a slider.
  ///
  /// Talkback/\VoiceOver provides users with the hint "slider" when a
  /// slider is focused.
  final bool? slider;

  /// If non-null, indicates that this subtree represents a keyboard key.
  final bool? keyboardKey;

  /// If non-null, indicates that this subtree is read only.
  ///
  /// Only applicable when [textField] is true.
  ///
  /// TalkBack/VoiceOver will treat it as non-editable text field.
  final bool? readOnly;

  /// If non-null, whether the node is able to hold input focus.
  ///
  /// If [focusable] is set to false, then [focused] must not be true.
  ///
  /// Input focus indicates that the node will receive keyboard events. It is not
  /// to be confused with accessibility focus. Accessibility focus is the
  /// green/black rectangular highlight that TalkBack/VoiceOver draws around the
  /// element it is reading, and is separate from input focus.
  @Deprecated(
    'Use focused instead. '
    'Setting focused automatically set focusable. '
    'This feature was deprecated after v3.36.0-0.0.pre.',
  )
  final bool? focusable;

  /// If non-null, whether the node currently holds input focus.
  ///
  /// If null, the node is not fosusable.
  ///
  /// At most one node in the tree should hold input focus at any point in time,
  /// and it should not be set to true if [focusable] is false.
  ///
  /// Input focus indicates that the node will receive keyboard events. It is not
  /// to be confused with accessibility focus. Accessibility focus is the
  /// green/black rectangular highlight that TalkBack/VoiceOver draws around the
  /// element it is reading, and is separate from input focus.
  final bool? focused;

  /// If non-null, indicates if this subtree or current node is blocked in a11y focus.
  ///
  /// This is for accessibility focus, which is the focus used by screen readers
  /// like TalkBack and VoiceOver. It is different from input focus, which is
  /// usually held by the element that currently responds to keyboard inputs.
  final AccessibilityFocusBlockType? accessibilityFocusBlockType;

  /// If non-null, whether a semantic node is in a mutually exclusive group.
  ///
  /// For example, a radio button is in a mutually exclusive group because only
  /// one radio button in that group can be marked as [checked].
  final bool? inMutuallyExclusiveGroup;

  /// If non-null, whether the node is considered hidden.
  ///
  /// Hidden elements are currently not visible on screen. They may be covered
  /// by other elements or positioned outside of the visible area of a viewport.
  ///
  /// Hidden elements cannot gain accessibility focus though regular touch. The
  /// only way they can be focused is by moving the focus to them via linear
  /// navigation.
  ///
  /// Platforms are free to completely ignore hidden elements and new platforms
  /// are encouraged to do so.
  ///
  /// Instead of marking an element as hidden it should usually be excluded from
  /// the semantics tree altogether. Hidden elements are only included in the
  /// semantics tree to work around platform limitations and they are mainly
  /// used to implement accessibility scrolling on iOS.
  final bool? hidden;

  /// If non-null, whether [value] should be obscured.
  ///
  /// This option is usually set in combination with [textField] to indicate
  /// that the text field contains a password (or other sensitive information).
  /// Doing so instructs screen readers to not read out the [value].
  final bool? obscured;

  /// Whether the [value] is coming from a field that supports multiline text
  /// editing.
  ///
  /// This option is only meaningful when [textField] is true to indicate
  /// whether it's a single-line or multiline text field.
  ///
  /// This option is null when [textField] is false.
  final bool? multiline;

  /// If non-null, whether the node corresponds to the root of a subtree for
  /// which a route name should be announced.
  ///
  /// Generally, this is set in combination with
  /// [SemanticsConfiguration.explicitChildNodes], since nodes with this flag
  /// are not considered focusable by Android or iOS.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.scopesRoute] for a description of how the announced
  ///    value is selected.
  final bool? scopesRoute;

  /// If non-null, whether the node contains the semantic label for a route.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.namesRoute] for a description of how the name is used.
  final bool? namesRoute;

  /// If non-null, whether the node represents an image.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isImage], for the flag this setting controls.
  final bool? image;

  /// If non-null, whether the node should be considered a live region.
  ///
  /// A live region indicates that updates to semantics node are important.
  /// Platforms may use this information to make polite announcements to the
  /// user to inform them of updates to this node.
  ///
  /// An example of a live region is a [SnackBar] widget. On Android and iOS,
  /// live region causes a polite announcement to be generated automatically,
  /// even if the widget does not have accessibility focus. This announcement
  /// may not be spoken if the OS accessibility services are already
  /// announcing something else, such as reading the label of a focused widget
  /// or providing a system announcement.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isLiveRegion], the semantics flag this setting controls.
  ///  * [SemanticsConfiguration.liveRegion], for a full description of a live region.
  final bool? liveRegion;

  /// If non-null, whether the node should be considered required.
  ///
  /// If true, user input is required on the semantics node before a form can
  /// be submitted. If false, the node is optional before a form can be
  /// submitted. If null, the node does not have a required semantics.
  ///
  /// For example, a login form requires its email text field to be non-empty.
  ///
  /// On web, this will set a `aria-required` attribute on the DOM element
  /// that corresponds to the semantics node.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isRequired], for the flag this setting controls.
  final bool? isRequired;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [textField] is true. Defaults to null,
  /// which means no limit is imposed on the text field.
  final int? maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [textField] is true. Must be set when
  /// [maxValueLength] is set.
  final int? currentValueLength;

  /// {@template flutter.semantics.SemanticsProperties.identifier}
  /// Provides an identifier for the semantics node in native accessibility hierarchy.
  ///
  /// This value is not exposed to the users of the app.
  ///
  /// It's usually used for UI testing with tools that work by querying the
  /// native accessibility, like UIAutomator, XCUITest, or Appium. It can be
  /// matched with [CommonFinders.bySemanticsIdentifier].
  ///
  /// On Android, this is used for `AccessibilityNodeInfo.setViewIdResourceName`.
  /// It'll be appear in accessibility hierarchy as `resource-id`.
  ///
  /// On iOS, this will set `UIAccessibilityElement.accessibilityIdentifier`.
  ///
  /// On web, this will set a `flt-semantics-identifier` attribute on the DOM element
  /// that corresponds to the semantics node.
  /// {@endtemplate}
  final String? identifier;

  /// {@template flutter.semantics.SemanticsProperties.traversalParentIdentifier}
  /// Provides an identifier for establishing parent-child relationships in the semantics
  /// traversal tree.
  ///
  /// This property is used to create a logical parent-child relationship between
  /// semantics nodes that may not be directly connected in the widget tree. It's
  /// primarily used with [OverlayPortal] to ensure proper accessibility traversal
  /// order when overlay content needs to be semantically connected to its parent
  /// widget.
  ///
  /// When a semantics node has a [traversalParentIdentifier], it indicates that
  /// this node can act as a parent for other nodes that reference this identifier
  /// in their [traversalChildIdentifier]. This allows assistive technologies
  /// to navigate the UI in the correct logical order.
  ///
  /// The `traversalParentIdentifier` must be unique in the semantics. No two
  /// semantics node can have the same `traversalParentIdentifier`. This unique
  /// identifier serves as the only reference for its traversal children. To
  /// graft other nodes as the traversal children of this node, assign this same
  /// value to their `traversalChildIdentifier`.
  /// {@endtemplate}
  final Object? traversalParentIdentifier;

  /// {@template flutter.semantics.SemanticsProperties.traversalChildIdentifier}
  /// Provides an identifier for establishing parent-child relationships in the semantics
  /// traversal tree.
  ///
  /// This property is used to create a logical parent-child relationship between
  /// semantics nodes that may not be directly connected in the widget tree. It's
  /// primarily used with [OverlayPortal] to ensure proper accessibility traversal
  /// order when overlay content needs to be semantically connected to its parent
  /// widget.
  ///
  /// When a semantics node has a [traversalChildIdentifier], it indicates that
  /// this node should be treated as a child of another node that has this same
  /// identifier as its [traversalParentIdentifier]. This allows assistive technologies
  /// to navigate the UI in the correct logical order.
  ///
  /// The `traversalChildIdentifier` value may be duplicated across multiple
  /// semantics nodes. To establish one or more nodes as the traversal children
  /// of a parent node, assign this identifier the same value as the parent's
  /// `traversalParentIdentifier`.
  /// {@endtemplate}
  final Object? traversalChildIdentifier;

  /// Provides a textual description of the widget.
  ///
  /// If a label is provided, there must either by an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [label] and [attributedLabel]. One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.label] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  ///  * [attributedLabel] for an [AttributedString] version of this property.
  final String? label;

  /// Provides an [AttributedString] version of textual description of the widget.
  ///
  /// If a [attributedLabel] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [label] and [attributedLabel]. One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedLabel] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [label] for a plain string version of this property.
  final AttributedString? attributedLabel;

  /// Provides a textual description of the value of the widget.
  ///
  /// If a value is provided, there must either by an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [value] and [attributedValue], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.value] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  ///  * [attributedLabel] for an [AttributedString] version of this property.
  final String? value;

  /// Provides an [AttributedString] version of textual description of the value
  /// of the widget.
  ///
  /// If a [attributedValue] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [value] and [attributedValue], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [value] for a plain string version of this property.
  final AttributedString? attributedValue;

  /// The value that [value] or [attributedValue] will become after a
  /// [SemanticsAction.increase] action has been performed on this widget.
  ///
  /// If a value is provided, [onIncrease] must also be set and there must
  /// either be an ambient [Directionality] or an explicit [textDirection]
  /// must be provided.
  ///
  /// Callers must not provide both [increasedValue] and
  /// [attributedIncreasedValue], One or both must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.increasedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [attributedIncreasedValue] for an [AttributedString] version of this
  ///    property.
  final String? increasedValue;

  /// The [AttributedString] that [value] or [attributedValue] will become after
  /// a [SemanticsAction.increase] action has been performed on this widget.
  ///
  /// If a [attributedIncreasedValue] is provided, [onIncrease] must also be set
  /// and there must either be an ambient [Directionality] or an explicit
  /// [textDirection] must be provided.
  ///
  /// Callers must not provide both [increasedValue] and
  /// [attributedIncreasedValue], One or both must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedIncreasedValue] for a description of
  ///    how this is exposed in TalkBack and VoiceOver.
  ///  * [increasedValue] for a plain string version of this property.
  final AttributedString? attributedIncreasedValue;

  /// The value that [value] or [attributedValue] will become after a
  /// [SemanticsAction.decrease] action has been performed on this widget.
  ///
  /// If a value is provided, [onDecrease] must also be set and there must
  /// either be an ambient [Directionality] or an explicit [textDirection]
  /// must be provided.
  ///
  /// Callers must not provide both [decreasedValue] and
  /// [attributedDecreasedValue], One or both must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.decreasedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [attributedDecreasedValue] for an [AttributedString] version of this
  ///    property.
  final String? decreasedValue;

  /// The [AttributedString] that [value] or [attributedValue] will become after
  /// a [SemanticsAction.decrease] action has been performed on this widget.
  ///
  /// If a [attributedDecreasedValue] is provided, [onDecrease] must also be set
  /// and there must either be an ambient [Directionality] or an explicit
  /// [textDirection] must be provided.
  ///
  /// Callers must not provide both [decreasedValue] and
  /// [attributedDecreasedValue], One or both must be null/// provided.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedDecreasedValue] for a description of
  ///    how this is exposed in TalkBack and VoiceOver.
  ///  * [decreasedValue] for a plain string version of this property.
  final AttributedString? attributedDecreasedValue;

  /// Provides a brief textual description of the result of an action performed
  /// on the widget.
  ///
  /// If a hint is provided, there must either be an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [hint] and [attributedHint], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.hint] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  ///  * [attributedHint] for an [AttributedString] version of this property.
  final String? hint;

  /// Provides an [AttributedString] version of brief textual description of the
  /// result of an action performed on the widget.
  ///
  /// If a [attributedHint] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  ///
  /// Callers must not provide both [hint] and [attributedHint], One or both
  /// must be null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.attributedHint] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  ///  * [hint] for a plain string version of this property.
  final AttributedString? attributedHint;

  /// Provides a textual description of the widget's tooltip.
  ///
  /// In Android, this property sets the `AccessibilityNodeInfo.setTooltipText`.
  /// In iOS, this property is appended to the end of the
  /// `UIAccessibilityElement.accessibilityLabel`.
  ///
  /// If a [tooltip] is provided, there must either by an ambient
  /// [Directionality] or an explicit [textDirection] should be provided.
  final String? tooltip;

  /// The heading level in the document structure.
  ///
  /// Screen readers will use this value to determine which part of the page
  /// structure this heading represents. A level 1 heading usually indicates
  /// the main heading of a page, a level 2 heading the first subsection,
  /// a level 3 is a subsection of that, and so on.
  ///
  /// On web, this sets the `aria-level` attribute (e.g., `aria-level="1"`).
  /// On Android, this sets the `isHeading` property for accessibility.
  final int? headingLevel;

  /// Overrides the default accessibility hints provided by the platform.
  ///
  /// This [hintOverrides] property does not affect how the platform processes hints;
  /// it only sets the custom text that will be read by assistive technology.
  ///
  /// On Android, these overrides replace the default hints for semantics nodes
  /// with tap or long-press actions. For example, if [SemanticsHintOverrides.onTapHint]
  /// is provided, instead of saying `Double tap to activate`, the screen reader
  /// will say `Double tap to <onTapHint>`.
  ///
  /// On iOS, this property is ignored, and default platform behavior applies.
  ///
  /// Example usage:
  /// ```dart
  /// const Semantics.fromProperties(
  ///  properties: SemanticsProperties(
  ///    hintOverrides: SemanticsHintOverrides(
  ///      onTapHint: 'open settings',
  ///    ),
  ///  ),
  ///  child: Text('button'),
  /// )
  /// ```
  final SemanticsHintOverrides? hintOverrides;

  /// The reading direction of the [label], [value], [increasedValue],
  /// [decreasedValue], and [hint].
  ///
  /// Defaults to the ambient [Directionality].
  final TextDirection? textDirection;

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  final SemanticsSortKey? sortKey;

  /// A tag to be applied to the child [SemanticsNode]s of this widget.
  ///
  /// The tag is added to all child [SemanticsNode]s that pass through the
  /// [RenderObject] corresponding to this widget while looking to be attached
  /// to a parent SemanticsNode.
  ///
  /// Tags are used to communicate to a parent SemanticsNode that a child
  /// SemanticsNode was passed through a particular RenderObject. The parent can
  /// use this information to determine the shape of the semantics tree.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.addTagForChildren], to which the tags provided
  ///    here will be passed.
  final SemanticsTag? tagForChildren;

  /// The URL that this node links to.
  ///
  /// On the web, this is used to set the `href` attribute of the DOM element.
  ///
  /// See also:
  ///
  /// * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href
  final Uri? linkUrl;

  /// The handler for [SemanticsAction.tap].
  ///
  /// This is the semantic equivalent of a user briefly tapping the screen with
  /// the finger without moving it. For example, a button should implement this
  /// action.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android *may* trigger this
  /// action by double-tapping the screen while an element is focused.
  ///
  /// Note: different OSes or assistive technologies may decide to interpret
  /// user inputs differently. Some may simulate real screen taps, while others
  /// may call semantics tap. One way to handle taps properly is to provide the
  /// same handler to both gesture tap and semantics tap.
  final VoidCallback? onTap;

  /// The handler for [SemanticsAction.longPress].
  ///
  /// This is the semantic equivalent of a user pressing and holding the screen
  /// with the finger for a few seconds without moving it.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android *may* trigger this
  /// action by double-tapping the screen without lifting the finger after the
  /// second tap.
  ///
  /// Note: different OSes or assistive technologies may decide to interpret
  /// user inputs differently. Some may simulate real long presses, while others
  /// may call semantics long press. One way to handle long press properly is to
  /// provide the same handler to both gesture long press and semantics long
  /// press.
  final VoidCallback? onLongPress;

  /// The handler for [SemanticsAction.scrollLeft].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from right to left. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping left with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollLeft;

  /// The handler for [SemanticsAction.scrollRight].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from left to right. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping right with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollRight;

  /// The handler for [SemanticsAction.scrollUp].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from bottom to top. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollUp;

  /// The handler for [SemanticsAction.scrollDown].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from top to bottom. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback? onScrollDown;

  /// The handler for [SemanticsAction.increase].
  ///
  /// This is a request to increase the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [increasedValue] must also be provided and
  /// [onIncrease] must ensure that [value] will be set to [increasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume up button.
  final VoidCallback? onIncrease;

  /// The handler for [SemanticsAction.decrease].
  ///
  /// This is a request to decrease the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [decreasedValue] must also be provided and
  /// [onDecrease] must ensure that [value] will be set to [decreasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume down button.
  final VoidCallback? onDecrease;

  /// The handler for [SemanticsAction.copy].
  ///
  /// This is a request to copy the current selection to the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback? onCopy;

  /// The handler for [SemanticsAction.cut].
  ///
  /// This is a request to cut the current selection and place it in the
  /// clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback? onCut;

  /// The handler for [SemanticsAction.paste].
  ///
  /// This is a request to paste the current content of the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback? onPaste;

  /// The handler for [SemanticsAction.moveCursorForwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field forward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume up key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorForwardByCharacter;

  /// The handler for [SemanticsAction.moveCursorBackwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorBackwardByCharacter;

  /// The handler for [SemanticsAction.moveCursorForwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorForwardByWord;

  /// The handler for [SemanticsAction.moveCursorBackwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler? onMoveCursorBackwardByWord;

  /// The handler for [SemanticsAction.setSelection].
  ///
  /// This handler is invoked when the user either wants to change the currently
  /// selected text in a text field or change the position of the cursor.
  ///
  /// TalkBack users can trigger this handler by selecting "Move cursor to
  /// beginning/end" or "Select all" from the local context menu.
  final SetSelectionHandler? onSetSelection;

  /// The handler for [SemanticsAction.setText].
  ///
  /// This handler is invoked when the user wants to replace the current text in
  /// the text field with a new text.
  ///
  /// Voice access users can trigger this handler by speaking `type <text>` to
  /// their Android devices.
  final SetTextHandler? onSetText;

  /// The handler for [SemanticsAction.didGainAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler gains
  /// the accessibility focus. The accessibility focus is the
  /// green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidLoseAccessibilityFocus], which is invoked when the accessibility
  ///    focus is removed from the node.
  ///  * [onFocus], which is invoked when the assistive technology requests that
  ///    the input focus is gained by a widget.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  final VoidCallback? onDidGainAccessibilityFocus;

  /// The handler for [SemanticsAction.didLoseAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler
  /// loses the accessibility focus. The accessibility focus is
  /// the green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidGainAccessibilityFocus], which is invoked when the node gains
  ///    accessibility focus.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  final VoidCallback? onDidLoseAccessibilityFocus;

  /// {@template flutter.semantics.SemanticsProperties.onFocus}
  /// The handler for [SemanticsAction.focus].
  ///
  /// This handler is invoked when the assistive technology requests that the
  /// focusable widget corresponding to this semantics node gain input focus.
  /// The [FocusNode] that manages the focus of the widget must gain focus. The
  /// widget must begin responding to relevant key events. For example:
  ///
  /// * Buttons must respond to tap/click events produced via keyboard shortcuts.
  /// * Text fields must become focused and editable, showing an on-screen
  ///   keyboard, if necessary.
  /// * Checkboxes, switches, and radio buttons must become toggleable using
  ///   keyboard shortcuts.
  ///
  /// Focus behavior is specific to the platform and to the assistive technology
  /// used. See the documentation of [SemanticsAction.focus] for more detail.
  ///
  /// See also:
  ///
  ///  * [onDidGainAccessibilityFocus], which is invoked when the node gains
  ///    accessibility focus.
  /// {@endtemplate}
  final VoidCallback? onFocus;

  /// The handler for [SemanticsAction.dismiss].
  ///
  /// This is a request to dismiss the currently focused node.
  ///
  /// TalkBack users on Android can trigger this action in the local context
  /// menu, and VoiceOver users on iOS can trigger this action with a standard
  /// gesture or menu option.
  final VoidCallback? onDismiss;

  /// The handler for [SemanticsAction.expand].
  ///
  /// This is a request to expand the currently focused node. For example, this
  /// action might be recognized by a dropdown.
  ///
  /// This handler should only be set when the node is in a collapsed state
  /// (i.e., [expanded] is false).
  final VoidCallback? onExpand;

  /// The handler for [SemanticsAction.collapse].
  ///
  /// This is a request to collapse the currently focused node. For example,
  /// this action might be recognized by a dropdown.
  ///
  /// This handler should only be set when the node is in an expanded state
  /// (i.e., [expanded] is true).
  final VoidCallback? onCollapse;

  /// A map from each supported [CustomSemanticsAction] to a provided handler.
  ///
  /// The handler associated with each custom action is called whenever a
  /// semantics action of type [SemanticsAction.customAction] is received. The
  /// provided argument will be an identifier used to retrieve an instance of
  /// a custom action which can then retrieve the correct handler from this map.
  ///
  /// See also:
  ///
  ///  * [CustomSemanticsAction], for an explanation of custom actions.
  final Map<CustomSemanticsAction, VoidCallback>? customSemanticsActions;

  /// {@template flutter.semantics.SemanticsProperties.role}
  /// A enum to describe what role the subtree represents.
  ///
  /// Setting the role for a widget subtree helps assistive technologies, such
  /// as screen readers, to understand and interact with the UI correctly.
  ///
  /// Defaults to [SemanticsRole.none] if not set, which means the subtree does
  /// not represent any complex ui or controls.
  ///
  /// For a list of available roles, see [SemanticsRole].
  /// {@endtemplate}
  final SemanticsRole? role;

  /// The [SemanticsNode.identifier]s of widgets controlled by this subtree.
  ///
  /// {@template flutter.semantics.SemanticsProperties.controlsNodes}
  /// If a widget is controlling the visibility or content of another widget,
  /// for example, [Tab]s control child visibilities of [TabBarView] or
  /// [ExpansionTile] controls visibility of its expanded content, one must
  /// assign a [SemanticsNode.identifier] to the content and also provide a set
  /// of identifiers including the content's identifier to this property.
  /// {@endtemplate}
  final Set<String>? controlsNodes;

  /// {@template flutter.semantics.SemanticsProperties.validationResult}
  /// Describes the validation result for a form field represented by this
  /// widget.
  ///
  /// Providing a validation result helps assistive technologies, such as screen
  /// readers, to communicate to the user whether they provided correct
  /// information in a form.
  ///
  /// Defaults to [SemanticsValidationResult.none] if not set, which means no
  /// validation information is available for the respective semantics node.
  ///
  /// For a list of available validation results, see [SemanticsValidationResult].
  /// {@endtemplate}
  final SemanticsValidationResult validationResult;

  /// {@template flutter.semantics.SemanticsProperties.hitTestBehavior}
  /// Describes how the semantic node should behave during hit testing.
  ///
  /// See [ui.SemanticsHitTestBehavior] for more details.
  /// {@endtemplate}
  final ui.SemanticsHitTestBehavior? hitTestBehavior;

  /// {@template flutter.semantics.SemanticsProperties.inputType}
  /// The input type for of a editable widget.
  ///
  /// This property is only used when the subtree represents a text field.
  ///
  /// Assistive technologies use this property to provide better information to
  /// users. For example, screen reader reads out the input type of text field
  /// when focused.
  /// {@endtemplate}
  final SemanticsInputType? inputType;

  /// {@template flutter.semantics.SemanticsProperties.maxValue}
  /// The maximum value of the node.
  ///
  /// Used in conjunction with [value] to define the current value and range
  /// of a node. A typical usage is for progress indicators, where [value]
  /// represents the current progress and [maxValue] defines the maximum
  /// possible value.
  ///
  /// {@endtemplate}
  final String? maxValue;

  /// {@template flutter.semantics.SemanticsProperties.minValue}
  /// The minimum value of the node.
  ///
  /// Used in conjunction with [value] to define the current value and range
  /// of a node. A typical usage is for progress indicators, where [value]
  /// represents the current progress and [minValue] defines the minimum
  /// possible value.
  ///
  /// {@endtemplate}
  final String? minValue;

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('checked', checked, defaultValue: null));
    properties.add(DiagnosticsProperty<bool>('mixed', mixed, defaultValue: null));
    properties.add(DiagnosticsProperty<bool>('expanded', expanded, defaultValue: null));
    properties.add(DiagnosticsProperty<bool>('selected', selected, defaultValue: null));
    properties.add(DiagnosticsProperty<bool>('isRequired', isRequired, defaultValue: null));
    properties.add(StringProperty('identifier', identifier, defaultValue: null));
    properties.add(
      DiagnosticsProperty<Object>(
        'traversalParentIdentifier',
        traversalParentIdentifier,
        defaultValue: null,
      ),
    );
    properties.add(
      DiagnosticsProperty<Object>(
        'traversalChildIdentifier',
        traversalChildIdentifier,
        defaultValue: null,
      ),
    );
    properties.add(StringProperty('label', label, defaultValue: null));
    properties.add(
      AttributedStringProperty('attributedLabel', attributedLabel, defaultValue: null),
    );
    properties.add(StringProperty('value', value, defaultValue: null));
    properties.add(
      AttributedStringProperty('attributedValue', attributedValue, defaultValue: null),
    );
    properties.add(StringProperty('increasedValue', value, defaultValue: null));
    properties.add(
      AttributedStringProperty(
        'attributedIncreasedValue',
        attributedIncreasedValue,
        defaultValue: null,
      ),
    );
    properties.add(StringProperty('decreasedValue', value, defaultValue: null));
    properties.add(
      AttributedStringProperty(
        'attributedDecreasedValue',
        attributedDecreasedValue,
        defaultValue: null,
      ),
    );
    properties.add(StringProperty('hint', hint, defaultValue: null));
    properties.add(AttributedStringProperty('attributedHint', attributedHint, defaultValue: null));
    properties.add(StringProperty('tooltip', tooltip, defaultValue: null));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
    properties.add(EnumProperty<SemanticsRole>('role', role, defaultValue: null));
    properties.add(
      EnumProperty<SemanticsValidationResult>(
        'validationResult',
        validationResult,
        defaultValue: SemanticsValidationResult.none,
      ),
    );
    properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
    properties.add(
      DiagnosticsProperty<SemanticsHintOverrides>(
        'hintOverrides',
        hintOverrides,
        defaultValue: null,
      ),
    );
  }

  @override
  String toStringShort() => objectRuntimeType(this, 'SemanticsProperties'); // the hashCode isn't important since we're immutable
}

/// In tests use this function to reset the counter used to generate
/// [SemanticsNode.id].
void debugResetSemanticsIdCounter() {
  SemanticsNode._lastIdentifier = 0;
}

/// A node that represents some semantic data.
///
/// The semantics tree is maintained during the semantics phase of the pipeline
/// (i.e., during [PipelineOwner.flushSemantics]), which happens after
/// compositing. The semantics tree is then uploaded into the engine for use
/// by assistive technology.
class SemanticsNode with DiagnosticableTreeMixin {
  /// Creates a semantic node.
  ///
  /// Each semantic node has a unique identifier that is assigned when the node
  /// is created.
  SemanticsNode({this.key, VoidCallback? showOnScreen})
    : _id = _generateNewId(),
      _showOnScreen = showOnScreen;

  /// Creates a semantic node to represent the root of the semantics tree.
  ///
  /// The root node is assigned an identifier of zero.
  SemanticsNode.root({this.key, VoidCallback? showOnScreen, required SemanticsOwner owner})
    : _id = 0,
      _showOnScreen = showOnScreen {
    attach(owner);
  }

  // The maximal semantic node identifier generated by the framework.
  //
  // The identifier range for semantic node IDs is split into 2, the least significant 16 bits are
  // reserved for framework generated IDs(generated with _generateNewId), and most significant 32
  // bits are reserved for engine generated IDs.
  static const int _maxFrameworkAccessibilityIdentifier = (1 << 16) - 1;

  static int _lastIdentifier = 0;
  static int _generateNewId() {
    _lastIdentifier = (_lastIdentifier + 1) % _maxFrameworkAccessibilityIdentifier;
    return _lastIdentifier;
  }

  /// Uniquely identifies this node in the list of sibling nodes.
  ///
  /// Keys are used during the construction of the semantics tree. They are not
  /// transferred to the engine.
  final Key? key;

  /// The unique identifier for this node.
  ///
  /// The root node has an id of zero. Other nodes are given a unique id
  /// when they are attached to a [SemanticsOwner]. If they are detached, their
  /// ids are invalid and should not be used.
  ///
  /// In rare circumstances, id may change if this node is detached and
  /// re-attached to the [SemanticsOwner]. This should only happen when the
  /// application has generated too many semantics nodes.
  int get id => _id;
  int _id;

  final VoidCallback? _showOnScreen;

  // GEOMETRY

  /// The transform from this node's coordinate system to its parent's coordinate system.
  ///
  /// By default, the transform is null, which represents the identity
  /// transformation (i.e., that this node has the same coordinate system as its
  /// parent).
  Matrix4? get transform => _transform;
  Matrix4? _transform;
  set transform(Matrix4? value) {
    if (!MatrixUtils.matrixEquals(_transform, value)) {
      _transform = value == null || MatrixUtils.isIdentity(value) ? null : value;
      _markDirty();
    }
  }

  // null means this node is not a traversal child and the transform is
  // the same as [transform] (or kIsWeb is true).
  Matrix4? _traversalChildTransform;
  // null represents the identity transform.
  Matrix4? get _traversalTransform {
    return kIsWeb ? transform : (_traversalChildTransform ?? transform);
  }

  /// The bounding box for this node in its coordinate system.
  Rect get rect => _rect;
  Rect _rect = Rect.zero;
  set rect(Rect value) {
    assert(value.isFinite, '$this (with $owner) tried to set a non-finite rect.');
    if (_rect != value) {
      _rect = value;
      _markDirty();
    }
  }

  /// The semantic clip from an ancestor that was applied to this node.
  ///
  /// Expressed in the coordinate system of the node. May be null if no clip has
  /// been applied.
  ///
  /// Descendant [SemanticsNode]s that are positioned outside of this rect will
  /// be excluded from the semantics tree. Descendant [SemanticsNode]s that are
  /// overlapping with this rect, but are outside of [parentPaintClipRect] will
  /// be included in the tree, but they will be marked as hidden because they
  /// are assumed to be not visible on screen.
  ///
  /// If this rect is null, all descendant [SemanticsNode]s outside of
  /// [parentPaintClipRect] will be excluded from the tree.
  ///
  /// If this rect is non-null it has to completely enclose
  /// [parentPaintClipRect]. If [parentPaintClipRect] is null this property is
  /// also null.
  Rect? parentSemanticsClipRect;

  /// The paint clip from an ancestor that was applied to this node.
  ///
  /// Expressed in the coordinate system of the node. May be null if no clip has
  /// been applied.
  ///
  /// Descendant [SemanticsNode]s that are positioned outside of this rect will
  /// either be excluded from the semantics tree (if they have no overlap with
  /// [parentSemanticsClipRect]) or they will be included and marked as hidden
  /// (if they are overlapping with [parentSemanticsClipRect]).
  ///
  /// This rect is completely enclosed by [parentSemanticsClipRect].
  ///
  /// If this rect is null [parentSemanticsClipRect] also has to be null.
  Rect? parentPaintClipRect;

  /// The index of this node within the parent's list of semantic children.
  ///
  /// This includes all semantic nodes, not just those currently in the
  /// child list. For example, if a scrollable has five children but the first
  /// two are not visible (and thus not included in the list of children), then
  /// the index of the last node will still be 4.
  int? indexInParent;

  /// Whether the node is invisible.
  ///
  /// A node whose [rect] is outside of the bounds of the screen and hence not
  /// reachable for users is considered invisible if its semantic information
  /// is not merged into a (partially) visible parent as indicated by
  /// [isMergedIntoParent].
  ///
  /// An invisible node can be safely dropped from the semantic tree without
  /// losing semantic information that is relevant for describing the content
  /// currently shown on screen.
  bool get isInvisible => !isMergedIntoParent && (rect.isEmpty || (transform?.isZero() ?? false));

  // MERGING

  /// Whether this node merges its semantic information into an ancestor node.
  ///
  /// This value indicates whether this node has any ancestors with
  /// [mergeAllDescendantsIntoThisNode] set to true.
  bool get isMergedIntoParent => _isMergedIntoParent;
  bool _isMergedIntoParent = false;
  set isMergedIntoParent(bool value) {
    if (_isMergedIntoParent == value) {
      return;
    }
    _isMergedIntoParent = value;
    parent?._markDirty();
  }

  /// Whether the user can interact with this node in assistive technologies.
  ///
  /// This node can still receive accessibility focus even if this is true.
  /// Setting this to true prevents the user from activating pointer related
  /// [SemanticsAction]s, such as [SemanticsAction.tap] or
  /// [SemanticsAction.longPress].
  bool get areUserActionsBlocked => _areUserActionsBlocked;
  bool _areUserActionsBlocked = false;
  set areUserActionsBlocked(bool value) {
    if (_areUserActionsBlocked == value) {
      return;
    }
    _areUserActionsBlocked = value;
    _markDirty();
  }

  /// Whether this node is taking part in a merge of semantic information.
  ///
  /// This returns true if the node is either merged into an ancestor node or if
  /// decedent nodes are merged into this node.
  ///
  /// See also:
  ///
  ///  * [isMergedIntoParent]
  ///  * [mergeAllDescendantsIntoThisNode]
  bool get isPartOfNodeMerging => mergeAllDescendantsIntoThisNode || isMergedIntoParent;

  /// Whether this node and all of its descendants should be treated as one logical entity.
  bool get mergeAllDescendantsIntoThisNode => _mergeAllDescendantsIntoThisNode;
  bool _mergeAllDescendantsIntoThisNode = _kEmptyConfig.isMergingSemanticsOfDescendants;

  // CHILDREN

  /// Contains the children in inverse hit test order (i.e. paint order).
  List<SemanticsNode>? _children;

  /// A snapshot of `newChildren` passed to [_replaceChildren] that we keep in
  /// debug mode. It supports the assertion that user does not mutate the list
  /// of children.
  late List<SemanticsNode> _debugPreviousSnapshot;

  void _replaceChildren(List<SemanticsNode> newChildren) {
    assert(!newChildren.any((SemanticsNode child) => child == this));
    assert(() {
      final seenChildren = <SemanticsNode>{};
      for (final child in newChildren) {
        assert(seenChildren.add(child));
      } // check for duplicate adds
      return true;
    }());

    // The goal of this function is updating sawChange.
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        child._dead = true;
      }
    }
    for (final child in newChildren) {
      child._dead = false;
    }
    var sawChange = false;
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        if (child._dead) {
          if (child.parent == this) {
            // we might have already had our child stolen from us by
            // another node that is deeper in the tree.
            _dropChild(child);
          }
          sawChange = true;
        }
      }
    }
    for (final child in newChildren) {
      if (child.parent != this) {
        if (child.parent != null) {
          // we're rebuilding the tree from the bottom up, so it's possible
          // that our child was, in the last pass, a child of one of our
          // ancestors. In that case, we drop the child eagerly here.
          // TODO(ianh): Find a way to assert that the same node didn't
          // actually appear in the tree in two places.
          child.parent?._dropChild(child);
        }
        assert(!child.attached);
        _adoptChild(child);
        sawChange = true;
      }
    }
    // Wait until the new children are adopted so isMergedIntoParent becomes
    // up-to-date.
    assert(() {
      if (identical(newChildren, _children)) {
        final mutationErrors = <DiagnosticsNode>[];
        if (newChildren.length != _debugPreviousSnapshot.length) {
          mutationErrors.add(
            ErrorDescription(
              "The list's length has changed from ${_debugPreviousSnapshot.length} "
              'to ${newChildren.length}.',
            ),
          );
        } else {
          for (var i = 0; i < newChildren.length; i++) {
            if (!identical(newChildren[i], _debugPreviousSnapshot[i])) {
              if (mutationErrors.isNotEmpty) {
                mutationErrors.add(ErrorSpacer());
              }
              mutationErrors.add(ErrorDescription('Child node at position $i was replaced:'));
              mutationErrors.add(
                _debugPreviousSnapshot[i].toDiagnosticsNode(
                  name: 'Previous child',
                  style: DiagnosticsTreeStyle.singleLine,
                ),
              );
              mutationErrors.add(
                newChildren[i].toDiagnosticsNode(
                  name: 'New child',
                  style: DiagnosticsTreeStyle.singleLine,
                ),
              );
            }
          }
        }
        if (mutationErrors.isNotEmpty) {
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary(
              'Failed to replace child semantics nodes because the list of `SemanticsNode`s was mutated.',
            ),
            ErrorHint(
              'Instead of mutating the existing list, create a new list containing the desired `SemanticsNode`s.',
            ),
            ErrorDescription('Error details:'),
            ...mutationErrors,
          ]);
        }
      }
      _debugPreviousSnapshot = List<SemanticsNode>.of(newChildren);

      var ancestor = this;
      while (ancestor.parent is SemanticsNode) {
        ancestor = ancestor.parent!;
      }
      assert(!newChildren.any((SemanticsNode child) => child == ancestor));
      return true;
    }());

    if (!sawChange && _children != null) {
      assert(newChildren.length == _children!.length);
      // Did the order change?
      for (var i = 0; i < _children!.length; i++) {
        if (_children![i].id != newChildren[i].id) {
          sawChange = true;
          break;
        }
      }
    }
    _children = newChildren;
    if (sawChange) {
      _markDirty();
    }
  }

  /// Whether this node has a non-zero number of children.
  bool get hasChildren => _children?.isNotEmpty ?? false;
  bool _dead = false;

  /// The number of children this node has in hit-test(paint) order.
  int get childrenCount => hasChildren ? _children!.length : 0;

  /// The number of children this node has in traversal order.
  int get childrenCountInTraversalOrder => _childrenInTraversalOrder().length;

  /// Visits the immediate children of this node.
  ///
  /// This function calls visitor for each immediate child until visitor returns
  /// false.
  void visitChildren(SemanticsNodeVisitor visitor) {
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        if (!visitor(child)) {
          return;
        }
      }
    }
  }

  /// Visit all the descendants of this node.
  ///
  /// This function calls visitor for each descendant in a pre-order traversal
  /// until visitor returns false. Returns true if all the visitor calls
  /// returned true, otherwise returns false.
  bool _visitDescendants(SemanticsNodeVisitor visitor) {
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        if (!visitor(child) || !child._visitDescendants(visitor)) {
          return false;
        }
      }
    }
    return true;
  }

  /// The owner for this node (null if unattached).
  ///
  /// The entire semantics tree that this node belongs to will have the same owner.
  SemanticsOwner? get owner => _owner;
  SemanticsOwner? _owner;

  /// Whether the semantics tree this node belongs to is attached to a [SemanticsOwner].
  ///
  /// This becomes true during the call to [attach].
  ///
  /// This becomes false during the call to [detach].
  bool get attached => _owner != null;

  /// The parent of this node in the semantics tree.
  ///
  /// The [parent] of the root node in the semantics tree is null.
  SemanticsNode? get parent => _parent;
  SemanticsNode? _parent;

  /// The real parent of this node in traversal order.
  ///
  /// This is useful for an [OverlayPortal] or a similar scenario where the node's
  /// hit-test parent (i.e., [parent]) and its traversal parent (i.e., [traversalParent])
  /// are different. If this node indicates an overlay portal child,
  /// [traversalParent] is its overlay portal parent node in traversal order.
  /// Otherwise, it is the same as [parent]. The [traversalParent] is used when
  /// the transform of this node needs to be updated in traversal order.
  SemanticsNode? get traversalParent => _traversalParent ?? parent;
  SemanticsNode? _traversalParent;
  set traversalParent(SemanticsNode? value) {
    if (_traversalParent == value) {
      return;
    }
    _traversalParent = value;
    _markDirty();
  }

  /// The depth of this node in the semantics tree.
  ///
  /// The depth of nodes in a tree monotonically increases as you traverse down
  /// the tree.  There's no guarantee regarding depth between siblings.
  ///
  /// The depth is used to ensure that nodes are processed in depth order.
  int get depth => _depth;
  int _depth = 0;

  /// The locale of this node.
  ///
  /// This property is used by assistive technologies to correctly interpret
  /// the content of this node.
  Locale? _locale;

  void _redepthChild(SemanticsNode child) {
    assert(child.owner == owner);
    if (child._depth <= _depth) {
      child._depth = _depth + 1;
      child._redepthChildren();
    }
  }

  void _redepthChildren() {
    _children?.forEach(_redepthChild);
  }

  void _updateChildMergeFlagRecursively(SemanticsNode child) {
    assert(child.owner == owner);
    final bool childShouldMergeToParent = isPartOfNodeMerging;

    if (childShouldMergeToParent == child.isMergedIntoParent) {
      return;
    }

    child.isMergedIntoParent = childShouldMergeToParent;

    if (child.mergeAllDescendantsIntoThisNode) {
      // No need to update the descendants since `child` has the merge flag set.
    } else {
      child._updateChildrenMergeFlags();
    }
  }

  void _updateChildrenMergeFlags() {
    _children?.forEach(_updateChildMergeFlagRecursively);
  }

  void _adoptChild(SemanticsNode child) {
    assert(child._parent == null);
    assert(() {
      var node = this;
      while (node.parent != null) {
        node = node.parent!;
      }
      assert(node != child); // indicates we are about to create a cycle
      return true;
    }());
    child._parent = this;
    if (attached) {
      child.attach(_owner!);
    }
    _redepthChild(child);
    // In most cases, child should have up to date `isMergedIntoParent` since
    // it was set during _RenderObjectSemantics.buildSemantics. However, it is
    // still possible that this child was an extra node introduced in
    // RenderObject.assembleSemanticsNode. We have to make sure their
    // `isMergedIntoParent` is updated correctly.
    _updateChildMergeFlagRecursively(child);
  }

  void _dropChild(SemanticsNode child) {
    assert(child._parent == this);
    assert(child.attached == attached);
    child._parent = null;
    if (attached) {
      child.detach();
    }
  }

  /// Mark this node as attached to the given owner.
  @visibleForTesting
  void attach(SemanticsOwner owner) {
    assert(_owner == null);
    _owner = owner;
    while (owner._nodes.containsKey(id)) {
      // Ids may repeat if the Flutter has generated > 2^16 ids. We need to keep
      // regenerating the id until we found an id that is not used.
      _id = _generateNewId();
    }
    owner._nodes[id] = this;
    owner._detachedNodes.remove(this);
    if (_dirty) {
      _dirty = false;
      _markDirty();
    }
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        child.attach(owner);
      }
    }
  }

  /// Mark this node as detached from its owner.
  @visibleForTesting
  void detach() {
    assert(_owner != null);
    assert(owner!._nodes.containsKey(id));
    assert(!owner!._detachedNodes.contains(this));
    owner!._nodes.remove(id);
    owner!._detachedNodes.add(this);

    // Clean up the according entry in owner._traversalParentNodes map.
    owner!._traversalParentNodes.removeWhere((Object key, SemanticsNode node) => node == this);
    // Clean up this node from the value set in owner._traversalChildNodes map.
    for (final Set<SemanticsNode> childSet in owner!._traversalChildNodes.values) {
      childSet.removeWhere((SemanticsNode node) => node == this);
    }

    _owner = null;
    assert(parent == null || attached == parent!.attached);
    if (_children != null) {
      for (final SemanticsNode child in _children!) {
        // The list of children may be stale and may contain nodes that have
        // been assigned to a different parent.
        if (child.parent == this) {
          child.detach();
        }
      }
    }
    // The other side will have forgotten this node if we ever send
    // it again, so make sure to mark it dirty so that it'll get
    // sent if it is resurrected.
    _markDirty();
  }

  // DIRTY MANAGEMENT

  bool _dirty = false;
  void _markDirty() {
    if (_dirty) {
      return;
    }
    _dirty = true;
    if (attached) {
      assert(!owner!._detachedNodes.contains(this));
      owner!._dirtyNodes.add(this);
    }
  }

  /// When asserts are enabled, returns whether node is marked as dirty.
  ///
  /// Otherwise, returns null.
  ///
  /// This getter is intended for use in framework unit tests. Applications must
  /// not depend on its value.
  @visibleForTesting
  bool? get debugIsDirty {
    bool? isDirty;
    assert(() {
      isDirty = _dirty;
      return true;
    }());
    return isDirty;
  }

  bool _isDifferentFromCurrentSemanticAnnotation(SemanticsConfiguration config) {
    return _attributedLabel != config.attributedLabel ||
        _attributedHint != config.attributedHint ||
        _attributedValue != config.attributedValue ||
        _attributedIncreasedValue != config.attributedIncreasedValue ||
        _attributedDecreasedValue != config.attributedDecreasedValue ||
        _tooltip != config.tooltip ||
        _flags != config._flags ||
        _textDirection != config.textDirection ||
        _sortKey != config._sortKey ||
        _textSelection != config._textSelection ||
        _scrollPosition != config._scrollPosition ||
        _scrollExtentMax != config._scrollExtentMax ||
        _scrollExtentMin != config._scrollExtentMin ||
        _actionsAsBits != config._actionsAsBits ||
        indexInParent != config.indexInParent ||
        platformViewId != config.platformViewId ||
        _maxValueLength != config._maxValueLength ||
        _currentValueLength != config._currentValueLength ||
        _mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants ||
        _areUserActionsBlocked != config.isBlockingUserActions ||
        _headingLevel != config._headingLevel ||
        _linkUrl != config._linkUrl ||
        _role != config.role ||
        _validationResult != config.validationResult ||
        _hitTestBehavior != config.hitTestBehavior ||
        _traversalChildIdentifier != config._traversalChildIdentifier ||
        _traversalParentIdentifier != config._traversalParentIdentifier ||
        _minValue != config._minValue ||
        _maxValue != config._maxValue;
  }

  // TAGS, LABELS, ACTIONS

  Map<SemanticsAction, SemanticsActionHandler> _actions = _kEmptyConfig._actions;
  Map<CustomSemanticsAction, VoidCallback> _customSemanticsActions =
      _kEmptyConfig._customSemanticsActions;

  int get _effectiveActionsAsBits =>
      _areUserActionsBlocked ? _actionsAsBits & _kUnblockedUserActions : _actionsAsBits;
  int _actionsAsBits = _kEmptyConfig._actionsAsBits;

  /// The [SemanticsTag]s this node is tagged with.
  ///
  /// Tags are used during the construction of the semantics tree. They are not
  /// transferred to the engine.
  Set<SemanticsTag>? tags;

  /// Whether this node is tagged with `tag`.
  bool isTagged(SemanticsTag tag) => tags != null && tags!.contains(tag);

  SemanticsFlags _flags = SemanticsFlags.none;

  /// Semantics flags.
  SemanticsFlags get flagsCollection => _flags;

  int get _flagsBitMask => _toBitMask(flagsCollection);

  /// Whether this node currently has a given [SemanticsFlag].
  @Deprecated(
    'Use flagsCollection instead. '
    'This feature was deprecated after v3.32.0-0.0.pre.',
  )
  bool hasFlag(SemanticsFlag flag) => (_flagsBitMask & flag.index) != 0;

  /// {@macro flutter.semantics.SemanticsProperties.identifier}
  String get identifier => _identifier;
  String _identifier = _kEmptyConfig.identifier;

  /// {@macro flutter.semantics.SemanticsProperties.traversalParentIdentifier}
  Object? get traversalParentIdentifier => _traversalParentIdentifier;
  Object? _traversalParentIdentifier;

  /// {@macro flutter.semantics.SemanticsProperties.traversalChildIdentifier}
  Object? get traversalChildIdentifier => _traversalChildIdentifier;
  Object? _traversalChildIdentifier;

  bool get _isTraversalParent => _traversalParentIdentifier != null;
  bool get _isTraversalChild => _traversalChildIdentifier != null;

  /// A textual description of this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedLabel].
  String get label => _attributedLabel.string;

  /// A textual description of this node in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [label], which exposes just the raw text.
  AttributedString get attributedLabel => _attributedLabel;
  AttributedString _attributedLabel = _kEmptyConfig.attributedLabel;

  /// A textual description for the current value of the node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedValue].
  String get value => _attributedValue.string;

  /// A textual description for the current value of the node in
  /// [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [value], which exposes just the raw text.
  AttributedString get attributedValue => _attributedValue;
  AttributedString _attributedValue = _kEmptyConfig.attributedValue;

  /// The value that [value] will have after a [SemanticsAction.increase] action
  /// has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.increase] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedIncreasedValue].
  String get increasedValue => _attributedIncreasedValue.string;

  /// The value in [AttributedString] format that [value] or [attributedValue]
  /// will have after a [SemanticsAction.increase] action has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.increase] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [increasedValue], which exposes just the raw text.
  AttributedString get attributedIncreasedValue => _attributedIncreasedValue;
  AttributedString _attributedIncreasedValue = _kEmptyConfig.attributedIncreasedValue;

  /// The value that [value] will have after a [SemanticsAction.decrease] action
  /// has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.decrease] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedDecreasedValue].
  String get decreasedValue => _attributedDecreasedValue.string;

  /// The value in [AttributedString] format that [value] or [attributedValue]
  /// will have after a [SemanticsAction.decrease] action has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.decrease] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [decreasedValue], which exposes just the raw text.
  AttributedString get attributedDecreasedValue => _attributedDecreasedValue;
  AttributedString _attributedDecreasedValue = _kEmptyConfig.attributedDecreasedValue;

  /// A brief description of the result of performing an action on this node.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// This exposes the raw text of the [attributedHint].
  String get hint => _attributedHint.string;

  /// A brief description of the result of performing an action on this node
  /// in [AttributedString] format.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also [hint], which exposes just the raw text.
  AttributedString get attributedHint => _attributedHint;
  AttributedString _attributedHint = _kEmptyConfig.attributedHint;

  /// A textual description of the widget's tooltip.
  ///
  /// The reading direction is given by [textDirection].
  String get tooltip => _tooltip;
  String _tooltip = _kEmptyConfig.tooltip;

  /// Provides hint values which override the default hints on supported
  /// platforms.
  SemanticsHintOverrides? get hintOverrides => _hintOverrides;
  SemanticsHintOverrides? _hintOverrides;

  /// The reading direction for [label], [value], [hint], [increasedValue], and
  /// [decreasedValue].
  TextDirection? get textDirection => _textDirection;
  TextDirection? _textDirection = _kEmptyConfig.textDirection;

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  SemanticsSortKey? get sortKey => _sortKey;
  SemanticsSortKey? _sortKey;

  /// The currently selected text (or the position of the cursor) within [value]
  /// if this node represents a text field.
  TextSelection? get textSelection => _textSelection;
  TextSelection? _textSelection;

  /// If this node represents a text field, this indicates whether or not it's
  /// a multiline text field.
  bool? get isMultiline => _isMultiline;
  bool? _isMultiline;

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  int? get scrollChildCount => _scrollChildCount;
  int? _scrollChildCount;

  /// The index of the first visible semantic child of a scroll node.
  int? get scrollIndex => _scrollIndex;
  int? _scrollIndex;

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  double? get scrollPosition => _scrollPosition;
  double? _scrollPosition;

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  double? get scrollExtentMax => _scrollExtentMax;
  double? _scrollExtentMax;

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent] from where this value is usually taken.
  double? get scrollExtentMin => _scrollExtentMin;
  double? _scrollExtentMin;

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  ///
  /// If this value is non-null, the SemanticsNode must not have any children
  /// as those would be replaced by the semantics nodes of the referenced
  /// platform view.
  ///
  /// See also:
  ///
  ///  * [AndroidView], which is the platform view for Android.
  ///  * [UiKitView], which is the platform view for iOS.
  int? get platformViewId => _platformViewId;
  int? _platformViewId;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
  /// to null, which means no limit is imposed on the text field.
  int? get maxValueLength => _maxValueLength;
  int? _maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Must be
  /// set when [maxValueLength] is set.
  int? get currentValueLength => _currentValueLength;
  int? _currentValueLength;

  /// The level of the widget as a heading within the structural hierarchy
  /// of the screen. A value of 1 indicates the highest level of structural
  /// hierarchy. A value of 2 indicates the next level, and so on.
  int get headingLevel => _headingLevel;
  int _headingLevel = _kEmptyConfig._headingLevel;

  /// The URL that this node links to.
  Uri? get linkUrl => _linkUrl;
  Uri? _linkUrl = _kEmptyConfig._linkUrl;

  /// {@template flutter.semantics.SemanticsNode.role}
  /// The role this node represents
  ///
  /// A semantics node's role helps assistive technologies, such as screen
  /// readers, understand and interact with the UI correctly.
  ///
  /// For a list of possible roles, see [SemanticsRole].
  /// {@endtemplate}
  SemanticsRole get role => _role;
  SemanticsRole _role = _kEmptyConfig.role;

  /// {@template flutter.semantics.SemanticsNode.controlsNodes}
  /// The [SemanticsNode.identifier]s of widgets controlled by this node.
  /// {@endtemplate}
  ///
  /// {@macro flutter.semantics.SemanticsProperties.controlsNodes}
  Set<String>? get controlsNodes => _controlsNodes;
  Set<String>? _controlsNodes = _kEmptyConfig.controlsNodes;

  /// {@macro flutter.semantics.SemanticsProperties.minValue}
  String? get minValue => _minValue;
  String? _minValue;

  /// {@macro flutter.semantics.SemanticsProperties.maxValue}
  String? get maxValue => _maxValue;
  String? _maxValue;

  /// {@macro flutter.semantics.SemanticsProperties.validationResult}
  SemanticsValidationResult get validationResult => _validationResult;
  SemanticsValidationResult _validationResult = _kEmptyConfig.validationResult;

  /// {@macro flutter.semantics.SemanticsProperties.hitTestBehavior}
  ui.SemanticsHitTestBehavior get hitTestBehavior => _hitTestBehavior;
  ui.SemanticsHitTestBehavior _hitTestBehavior = ui.SemanticsHitTestBehavior.defer;

  /// {@template flutter.semantics.SemanticsNode.inputType}
  /// The input type for of a editable node.
  ///
  /// This property is only used when this node represents a text field.
  ///
  /// Assistive technologies use this property to provide better information to
  /// users. For example, screen reader reads out the input type of text field
  /// when focused.
  /// {@endtemplate}
  SemanticsInputType get inputType => _inputType;
  SemanticsInputType _inputType = _kEmptyConfig.inputType;

  bool _canPerformAction(SemanticsAction action) => _actions.containsKey(action);

  static final SemanticsConfiguration _kEmptyConfig = SemanticsConfiguration();

  /// Reconfigures the properties of this object to describe the configuration
  /// provided in the `config` argument and the children listed in the
  /// `childrenInInversePaintOrder` argument.
  ///
  /// The arguments may be null; this represents an empty configuration (all
  /// values at their defaults, no children).
  ///
  /// No reference is kept to the [SemanticsConfiguration] object, but the child
  /// list is used as-is and should therefore not be changed after this call.
  void updateWith({
    required SemanticsConfiguration? config,
    List<SemanticsNode>? childrenInInversePaintOrder,
  }) {
    config ??= _kEmptyConfig;
    if (_isDifferentFromCurrentSemanticAnnotation(config)) {
      _markDirty();
    }

    assert(
      config.platformViewId == null ||
          childrenInInversePaintOrder == null ||
          childrenInInversePaintOrder.isEmpty,
      'SemanticsNodes with children must not specify a platformViewId.',
    );

    final mergeAllDescendantsIntoThisNodeValueChanged =
        _mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants;

    _identifier = config.identifier;
    _traversalParentIdentifier = config.traversalParentIdentifier;
    _traversalChildIdentifier = config.traversalChildIdentifier;
    _attributedLabel = config.attributedLabel;
    _attributedValue = config.attributedValue;
    _attributedIncreasedValue = config.attributedIncreasedValue;
    _attributedDecreasedValue = config.attributedDecreasedValue;
    _attributedHint = config.attributedHint;
    _tooltip = config.tooltip;
    _hintOverrides = config.hintOverrides;
    _flags = config._flags;
    _textDirection = config.textDirection;
    _sortKey = config.sortKey;
    _actions = Map<SemanticsAction, SemanticsActionHandler>.of(config._actions);
    _customSemanticsActions = Map<CustomSemanticsAction, VoidCallback>.of(
      config._customSemanticsActions,
    );
    _actionsAsBits = config._actionsAsBits;
    _textSelection = config._textSelection;
    _isMultiline = config.isMultiline;
    _scrollPosition = config._scrollPosition;
    _scrollExtentMax = config._scrollExtentMax;
    _scrollExtentMin = config._scrollExtentMin;
    _mergeAllDescendantsIntoThisNode = config.isMergingSemanticsOfDescendants;
    _scrollChildCount = config.scrollChildCount;
    _scrollIndex = config.scrollIndex;
    indexInParent = config.indexInParent;
    _platformViewId = config._platformViewId;
    _maxValueLength = config._maxValueLength;
    _currentValueLength = config._currentValueLength;
    _areUserActionsBlocked = config.isBlockingUserActions;
    _headingLevel = config._headingLevel;
    _linkUrl = config._linkUrl;
    _role = config._role;
    _controlsNodes = config._controlsNodes;
    _validationResult = config._validationResult;
    _hitTestBehavior = config._hitTestBehavior;
    _inputType = config._inputType;
    _locale = config.locale;

    _minValue = config.minValue;
    _maxValue = config.maxValue;
    _replaceChildren(childrenInInversePaintOrder ?? const <SemanticsNode>[]);

    if (mergeAllDescendantsIntoThisNodeValueChanged) {
      _updateChildrenMergeFlags();
    }

    assert(
      !_canPerformAction(SemanticsAction.increase) || (value == '') == (increasedValue == ''),
      'A SemanticsNode with action "increase" needs to be annotated with either both "value" and "increasedValue" or neither',
    );
    assert(
      !_canPerformAction(SemanticsAction.decrease) || (value == '') == (decreasedValue == ''),
      'A SemanticsNode with action "decrease" needs to be annotated with either both "value" and "decreasedValue" or neither',
    );
  }

  /// Returns a summary of the semantics for this node.
  ///
  /// If this node has [mergeAllDescendantsIntoThisNode], then the returned data
  /// includes the information from this node's descendants. Otherwise, the
  /// returned data matches the data on this node.
  SemanticsData getSemanticsData() {
    SemanticsFlags flags = _flags;
    // Can't use _effectiveActionsAsBits here. The filtering of action bits
    // must be done after the merging the its descendants.
    int actions = _actionsAsBits;
    String identifier = _identifier;
    Object? traversalParentIdentifier = _traversalParentIdentifier;
    Object? traversalChildIdentifier = _traversalChildIdentifier;
    AttributedString attributedLabel = _attributedLabel;
    AttributedString attributedValue = _attributedValue;
    AttributedString attributedIncreasedValue = _attributedIncreasedValue;
    AttributedString attributedDecreasedValue = _attributedDecreasedValue;
    AttributedString attributedHint = _attributedHint;
    String tooltip = _tooltip;
    TextDirection? textDirection = _textDirection;
    Set<SemanticsTag>? mergedTags = tags == null ? null : Set<SemanticsTag>.of(tags!);
    TextSelection? textSelection = _textSelection;
    int? scrollChildCount = _scrollChildCount;
    int? scrollIndex = _scrollIndex;
    double? scrollPosition = _scrollPosition;
    double? scrollExtentMax = _scrollExtentMax;
    double? scrollExtentMin = _scrollExtentMin;
    int? platformViewId = _platformViewId;
    int? maxValueLength = _maxValueLength;
    int? currentValueLength = _currentValueLength;
    int headingLevel = _headingLevel;
    Uri? linkUrl = _linkUrl;
    SemanticsRole role = _role;
    Set<String>? controlsNodes = _controlsNodes;
    SemanticsValidationResult validationResult = _validationResult;
    ui.SemanticsHitTestBehavior hitTestBehavior = _hitTestBehavior;
    SemanticsInputType inputType = _inputType;
    final Locale? locale = _locale;
    final customSemanticsActionIds = <int>{};
    String? minValue = _minValue;
    String? maxValue = _maxValue;
    for (final CustomSemanticsAction action in _customSemanticsActions.keys) {
      customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
    }
    if (hintOverrides != null) {
      if (hintOverrides!.onTapHint != null) {
        final action = CustomSemanticsAction.overridingAction(
          hint: hintOverrides!.onTapHint!,
          action: SemanticsAction.tap,
        );
        customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
      }
      if (hintOverrides!.onLongPressHint != null) {
        final action = CustomSemanticsAction.overridingAction(
          hint: hintOverrides!.onLongPressHint!,
          action: SemanticsAction.longPress,
        );
        customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
      }
    }

    if (mergeAllDescendantsIntoThisNode) {
      _visitDescendants((SemanticsNode node) {
        assert(node.isMergedIntoParent);
        flags = flags.merge(node._flags);
        actions |= node._effectiveActionsAsBits;
        textDirection ??= node._textDirection;
        textSelection ??= node._textSelection;
        scrollChildCount ??= node._scrollChildCount;
        scrollIndex ??= node._scrollIndex;
        scrollPosition ??= node._scrollPosition;
        scrollExtentMax ??= node._scrollExtentMax;
        scrollExtentMin ??= node._scrollExtentMin;
        platformViewId ??= node._platformViewId;
        maxValueLength ??= node._maxValueLength;
        currentValueLength ??= node._currentValueLength;
        linkUrl ??= node._linkUrl;
        headingLevel = _mergeHeadingLevels(
          sourceLevel: node._headingLevel,
          targetLevel: headingLevel,
        );

        if (identifier == '') {
          identifier = node._identifier;
        }
        traversalParentIdentifier ??= node.traversalParentIdentifier;
        traversalChildIdentifier ??= node.traversalChildIdentifier;
        if (attributedValue.string == '') {
          attributedValue = node._attributedValue;
        }
        if (attributedIncreasedValue.string == '') {
          attributedIncreasedValue = node._attributedIncreasedValue;
        }
        if (attributedDecreasedValue.string == '') {
          attributedDecreasedValue = node._attributedDecreasedValue;
        }
        if (role == SemanticsRole.none) {
          role = node._role;
        }
        if (inputType == SemanticsInputType.none) {
          inputType = node._inputType;
        }
        if (hitTestBehavior == ui.SemanticsHitTestBehavior.defer) {
          hitTestBehavior = node._hitTestBehavior;
        }
        if (tooltip == '') {
          tooltip = node._tooltip;
        }
        if (node.tags != null) {
          mergedTags ??= <SemanticsTag>{};
          mergedTags!.addAll(node.tags!);
        }
        for (final CustomSemanticsAction action in node._customSemanticsActions.keys) {
          customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
        }
        if (node.hintOverrides != null) {
          if (node.hintOverrides!.onTapHint != null) {
            final action = CustomSemanticsAction.overridingAction(
              hint: node.hintOverrides!.onTapHint!,
              action: SemanticsAction.tap,
            );
            customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
          }
          if (node.hintOverrides!.onLongPressHint != null) {
            final action = CustomSemanticsAction.overridingAction(
              hint: node.hintOverrides!.onLongPressHint!,
              action: SemanticsAction.longPress,
            );
            customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
          }
        }
        attributedLabel = _concatAttributedString(
          thisAttributedString: attributedLabel,
          thisTextDirection: textDirection,
          otherAttributedString: node._attributedLabel,
          otherTextDirection: node._textDirection,
        );
        attributedHint = _concatAttributedString(
          thisAttributedString: attributedHint,
          thisTextDirection: textDirection,
          otherAttributedString: node._attributedHint,
          otherTextDirection: node._textDirection,
        );

        if (controlsNodes == null) {
          controlsNodes = node._controlsNodes;
        } else if (node._controlsNodes != null) {
          controlsNodes = <String>{...controlsNodes!, ...node._controlsNodes!};
        }

        minValue ??= node._minValue;
        maxValue ??= node._maxValue;

        if (validationResult == SemanticsValidationResult.none) {
          validationResult = node._validationResult;
        } else if (validationResult == SemanticsValidationResult.valid) {
          // When merging nodes, invalid validation result takes precedence.
          // Otherwise, validation information could be lost.
          if (node._validationResult != SemanticsValidationResult.none &&
              node._validationResult != SemanticsValidationResult.valid) {
            validationResult = node._validationResult;
          }
        }

        return true;
      });
    }

    return SemanticsData(
      flagsCollection: flags,
      actions: _areUserActionsBlocked ? actions & _kUnblockedUserActions : actions,
      identifier: identifier,
      traversalParentIdentifier: traversalParentIdentifier,
      traversalChildIdentifier: traversalChildIdentifier,
      attributedLabel: attributedLabel,
      attributedValue: attributedValue,
      attributedIncreasedValue: attributedIncreasedValue,
      attributedDecreasedValue: attributedDecreasedValue,
      attributedHint: attributedHint,
      tooltip: tooltip,
      textDirection: textDirection,
      rect: rect,
      transform: transform,
      tags: mergedTags,
      textSelection: textSelection,
      scrollChildCount: scrollChildCount,
      scrollIndex: scrollIndex,
      scrollPosition: scrollPosition,
      scrollExtentMax: scrollExtentMax,
      scrollExtentMin: scrollExtentMin,
      platformViewId: platformViewId,
      maxValueLength: maxValueLength,
      currentValueLength: currentValueLength,
      customSemanticsActionIds: customSemanticsActionIds.toList()..sort(),
      headingLevel: headingLevel,
      linkUrl: linkUrl,
      role: role,
      controlsNodes: controlsNodes,
      validationResult: validationResult,
      hitTestBehavior: hitTestBehavior,
      inputType: inputType,
      locale: locale,
      minValue: minValue,
      maxValue: maxValue,
    );
  }

  static final Int32List _kEmptyChildList = Int32List(0);
  static final Int32List _kEmptyCustomSemanticsActionsList = Int32List(0);
  static final Matrix4 _kIdentityTransform = Matrix4.identity();

  static Matrix4 _computeTraversalTransform({
    required SemanticsNode parent,
    required SemanticsNode child,
  }) {
    final traversalTransform = Matrix4.identity();
    Matrix4? parentToCommonAncestorTransform;
    var fromNode = child;
    var toNode = parent;

    // Find the common ancestor.
    while (!identical(fromNode, toNode)) {
      final int fromDepth = fromNode.depth;
      final int toDepth = toNode.depth;

      if (fromDepth >= toDepth) {
        if (fromNode.transform case final Matrix4 transform?) {
          traversalTransform.multiply(transform);
        }
        fromNode = fromNode.parent!;
      }
      if (fromDepth <= toDepth) {
        parentToCommonAncestorTransform ??= Matrix4.identity();
        if (toNode.transform case final Matrix4 transform?) {
          parentToCommonAncestorTransform.multiply(transform);
        }
        toNode = toNode.parent!;
      }
    }

    if (parentToCommonAncestorTransform != null) {
      if (parentToCommonAncestorTransform.invert() != 0) {
        traversalTransform.multiply(parentToCommonAncestorTransform);
      } else {
        traversalTransform.setZero();
      }
    }
    return traversalTransform;
  }

  Int32List _childrenIdInTraversalOrder() {
    final List<SemanticsNode> sortedChildren = _childrenInTraversalOrder();

    final childrenInTraversalOrder = Int32List(sortedChildren.length);
    for (var i = 0; i < sortedChildren.length; i += 1) {
      childrenInTraversalOrder[i] = sortedChildren[i].id;
    }
    return childrenInTraversalOrder;
  }

  void _addToUpdate(SemanticsUpdateBuilder builder, Set<int> customSemanticsActionIdsUpdate) {
    assert(_dirty || _isTraversalParent);
    final SemanticsData data = getSemanticsData();
    assert(() {
      final FlutterError? error = _DebugSemanticsRoleChecks._checkSemanticsData(this);
      if (error != null) {
        throw error;
      }
      return true;
    }());
    final Int32List childrenInTraversalOrder;
    final Int32List childrenInHitTestOrder;
    if (!hasChildren || mergeAllDescendantsIntoThisNode) {
      if (_isTraversalParent && !kIsWeb) {
        // If the current node is a traversal parent node but it has no
        // children in hit-test order, it means childrenIntraversalOrder will
        // only contain its traversalChildren in _traversalChildNodes map.
        if (owner != null && owner!._traversalChildNodes.containsKey(traversalParentIdentifier)) {
          final Set<SemanticsNode> traversalChildren =
              owner!._traversalChildNodes[traversalParentIdentifier]!;
          var index = 0;
          childrenInTraversalOrder = Int32List(traversalChildren.length);
          for (final node in traversalChildren) {
            if (node.attached) {
              childrenInTraversalOrder[index] = node.id;
              index += 1;
            }
          }
        } else {
          childrenInTraversalOrder = _kEmptyChildList;
        }
        childrenInHitTestOrder = _kEmptyChildList;
      } else {
        childrenInTraversalOrder = _kEmptyChildList;
        childrenInHitTestOrder = _kEmptyChildList;
      }
    } else {
      childrenInTraversalOrder = _childrenIdInTraversalOrder();

      final int childCount = _children!.length;
      // _children is sorted in paint order, so we invert it to get the hit test
      // order.
      childrenInHitTestOrder = Int32List(childCount);
      for (int i = childCount - 1; i >= 0; i -= 1) {
        childrenInHitTestOrder[i] = _children![childCount - i - 1].id;
      }
    }

    Int32List? customSemanticsActionIds;
    if (data.customSemanticsActionIds?.isNotEmpty ?? false) {
      customSemanticsActionIds = Int32List(data.customSemanticsActionIds!.length);
      for (var i = 0; i < data.customSemanticsActionIds!.length; i++) {
        customSemanticsActionIds[i] = data.customSemanticsActionIds![i];
        customSemanticsActionIdsUpdate.add(data.customSemanticsActionIds![i]);
      }
    }

    var traversalParentId = -1;
    if (data.traversalChildIdentifier case final Object identifier?) {
      if (owner!._traversalParentNodes[identifier] case final SemanticsNode parentNode?) {
        traversalParentId = parentNode.id;
      }
    }
    final Object? childIdentifier = traversalChildIdentifier;
    if (childIdentifier != null) {
      traversalParent = owner!._traversalParentNodes[childIdentifier];
      if (!kIsWeb) {
        _traversalChildTransform = _computeTraversalTransform(
          parent: traversalParent!,
          child: this,
        );
      }
    }

    builder.updateNode(
      id: id,
      flags: data.flagsCollection,
      actions: data.actions,
      rect: data.rect,
      identifier: data.identifier,
      label: data.attributedLabel.string,
      labelAttributes: data.attributedLabel.attributes,
      value: data.attributedValue.string,
      valueAttributes: data.attributedValue.attributes,
      increasedValue: data.attributedIncreasedValue.string,
      increasedValueAttributes: data.attributedIncreasedValue.attributes,
      decreasedValue: data.attributedDecreasedValue.string,
      decreasedValueAttributes: data.attributedDecreasedValue.attributes,
      hint: data.attributedHint.string,
      hintAttributes: data.attributedHint.attributes,
      tooltip: data.tooltip,
      textDirection: data.textDirection,
      textSelectionBase: data.textSelection != null ? data.textSelection!.baseOffset : -1,
      textSelectionExtent: data.textSelection != null ? data.textSelection!.extentOffset : -1,
      platformViewId: data.platformViewId ?? -1,
      maxValueLength: data.maxValueLength ?? -1,
      currentValueLength: data.currentValueLength ?? -1,
      scrollChildren: data.scrollChildCount ?? 0,
      scrollIndex: data.scrollIndex ?? 0,
      scrollPosition: data.scrollPosition ?? double.nan,
      scrollExtentMax: data.scrollExtentMax ?? double.nan,
      scrollExtentMin: data.scrollExtentMin ?? double.nan,
      transform: (_traversalTransform ?? _kIdentityTransform).storage,
      traversalParent: traversalParentId,
      hitTestTransform: (data.transform ?? _kIdentityTransform).storage,
      childrenInTraversalOrder: childrenInTraversalOrder,
      childrenInHitTestOrder: childrenInHitTestOrder,
      additionalActions: customSemanticsActionIds ?? _kEmptyCustomSemanticsActionsList,
      headingLevel: data.headingLevel,
      linkUrl: data.linkUrl?.toString() ?? '',
      role: data.role,
      controlsNodes: data.controlsNodes?.toList(),
      validationResult: data.validationResult,
      hitTestBehavior: data.hitTestBehavior,
      inputType: data.inputType,
      locale: data.locale,
      minValue: data.minValue ?? '',
      maxValue: data.maxValue ?? '',
    );
    _dirty = false;
  }

  // Generate a children list in traversal order. Add tree grafting when needed
  // so that all overlay portal child nodes have correct overlay portal parent
  // in traversal order. On web, the childrenInTraversalOrder is kept the same
  // as the _children(paint-order) list because of the assumption that requires both
  // childrenInTraversalOrder and childrenInHitTestOrder have the same length.
  // To ensure the correctness of the childrenInTraversalOrder, ARIA-owns is used
  // on the web side.
  List<SemanticsNode>? _updateChildrenInTraversalOrder() {
    if (kIsWeb) {
      return _children;
    }

    final updatedChildren = <SemanticsNode>[];
    for (final SemanticsNode child in _children!) {
      if (child._isTraversalChild && !_isTraversalParent) {
        // If the child node is a traversal child, but the current node is
        // not a traversal parent, it means the child node should be
        // grafted to be a child of a traversal parent node that has the
        // same identifier as the child. So this child should be removed from
        // the current node's children list; i.e., we don't add it to
        // updatedChildren list.
        //
        // A corner case is the traversal parent of the traversal child, in paint
        // order, is the child of the traversal child. In this case, no grafting
        // needed, otherwise, it will cause infinite loop.
        SemanticsNode? traversalParent =
            owner!._traversalParentNodes[child.getSemanticsData().traversalChildIdentifier];
        final int? traversalParentId = traversalParent?.id;
        while (traversalParent != null) {
          if (traversalParent == child) {
            throw FlutterError(
              'The traversalParent $traversalParentId cannot be the child of the traversalChild ${child.id} in hit-test order',
            );
          }
          traversalParent = traversalParent.parent;
        }

        continue;
      }

      updatedChildren.add(child);
    }

    // If the current node is a traversal parent node, it means that part of its
    // traversal children might be on other branches of the hit-test tree and
    // need to be grafted. To fix the traversal order, get the according traversal
    // children from _traversalChildNodes and add them to the children list
    // of this current node.
    if (_isTraversalParent) {
      final Set<SemanticsNode>? traversalChildren =
          owner?._traversalChildNodes[traversalParentIdentifier!];
      if (traversalChildren != null) {
        // When traversal children are grafted from other branches, make sure
        // these children are not ancestors of the traversal parent. Otherwise,
        // it will cause infinite loop.
        var currentNode = this;
        while (currentNode.parent != null) {
          currentNode = currentNode.parent!;
          if (traversalChildren.contains(currentNode)) {
            throw FlutterError(
              'The traversalParent $id cannot be the child of the traversalChild ${currentNode.id} in hit-test order',
            );
          }
        }
        for (final SemanticsNode node in traversalChildren) {
          if (node.attached) {
            updatedChildren.add(node);
          }
        }
      }
    }

    return updatedChildren;
  }

  /// Builds a new list made of [_children] sorted in semantic traversal order.
  List<SemanticsNode> _childrenInTraversalOrder() {
    final List<SemanticsNode>? updatedChildren = _updateChildrenInTraversalOrder();

    TextDirection? inheritedTextDirection = textDirection;
    SemanticsNode? ancestor = parent;
    while (inheritedTextDirection == null && ancestor != null) {
      inheritedTextDirection = ancestor.textDirection;
      ancestor = ancestor.parent;
    }

    List<SemanticsNode>? childrenInDefaultOrder;
    if (inheritedTextDirection != null) {
      childrenInDefaultOrder = _childrenInDefaultOrder(updatedChildren!, inheritedTextDirection);
    } else {
      // In the absence of text direction default to paint order.
      childrenInDefaultOrder = updatedChildren;
    }
    // List.sort does not guarantee stable sort order. Therefore, children are
    // first partitioned into groups that have compatible sort keys, i.e. keys
    // in the same group can be compared to each other. These groups stay in
    // the same place. Only children within the same group are sorted.
    final everythingSorted = <_TraversalSortNode>[];
    final sortNodes = <_TraversalSortNode>[];
    SemanticsSortKey? lastSortKey;
    for (var position = 0; position < childrenInDefaultOrder!.length; position += 1) {
      final SemanticsNode child = childrenInDefaultOrder[position];
      final SemanticsSortKey? sortKey = child.sortKey;
      lastSortKey = position > 0 ? childrenInDefaultOrder[position - 1].sortKey : null;
      final bool isCompatibleWithPreviousSortKey =
          position == 0 ||
          sortKey.runtimeType == lastSortKey.runtimeType &&
              (sortKey == null || sortKey.name == lastSortKey!.name);
      if (!isCompatibleWithPreviousSortKey && sortNodes.isNotEmpty) {
        // Do not sort groups with null sort keys. List.sort does not guarantee
        // a stable sort order.
        if (lastSortKey != null) {
          sortNodes.sort();
        }
        everythingSorted.addAll(sortNodes);
        sortNodes.clear();
      }

      sortNodes.add(_TraversalSortNode(node: child, sortKey: sortKey, position: position));
    }

    // Do not sort groups with null sort keys. List.sort does not guarantee
    // a stable sort order.
    if (lastSortKey != null) {
      sortNodes.sort();
    }
    everythingSorted.addAll(sortNodes);
    return everythingSorted
        .map<SemanticsNode>((_TraversalSortNode sortNode) => sortNode.node)
        .toList();
  }

  /// Sends a [SemanticsEvent] associated with this [SemanticsNode].
  ///
  /// Semantics events should be sent to inform interested parties (like
  /// the accessibility system of the operating system) about changes to the UI.
  void sendEvent(SemanticsEvent event) {
    if (!attached) {
      return;
    }
    SystemChannels.accessibility.send(event.toMap(nodeId: id));
  }

  bool _debugIsActionBlocked(SemanticsAction action) {
    var result = false;
    assert(() {
      result = (_effectiveActionsAsBits & action.index) == 0;
      return true;
    }());
    return result;
  }

  @override
  String toStringShort() => '${objectRuntimeType(this, 'SemanticsNode')}#$id';

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    var hideOwner = true;
    if (_dirty) {
      final bool inDirtyNodes = owner != null && owner!._dirtyNodes.contains(this);
      properties.add(
        FlagProperty('inDirtyNodes', value: inDirtyNodes, ifTrue: 'dirty', ifFalse: 'STALE'),
      );
      hideOwner = inDirtyNodes;
    }
    properties.add(
      DiagnosticsProperty<SemanticsOwner>(
        'owner',
        owner,
        level: hideOwner ? DiagnosticLevel.hidden : DiagnosticLevel.info,
      ),
    );
    properties.add(
      FlagProperty('isMergedIntoParent', value: isMergedIntoParent, ifTrue: 'merged up ⬆️'),
    );
    properties.add(
      FlagProperty(
        'mergeAllDescendantsIntoThisNode',
        value: mergeAllDescendantsIntoThisNode,
        ifTrue: 'merge boundary ⛔️',
      ),
    );
    if (_locale != null) {
      properties.add(StringProperty('locale', _locale.toString()));
    }
    final Offset? offset = transform != null ? MatrixUtils.getAsTranslation(transform!) : null;
    if (offset != null) {
      properties.add(DiagnosticsProperty<Rect>('rect', rect.shift(offset), showName: false));
    } else {
      final double? scale = transform != null ? MatrixUtils.getAsScale(transform!) : null;
      String? description;
      if (scale != null) {
        description = '$rect scaled by ${scale.toStringAsFixed(1)}x';
      } else if (transform != null && !MatrixUtils.isIdentity(transform!)) {
        final String matrix = transform
            .toString()
            .split('\n')
            .take(4)
            .map<String>((String line) => line.substring(4))
            .join('; ');
        description = '$rect with transform [$matrix]';
      }
      properties.add(
        DiagnosticsProperty<Rect>('rect', rect, description: description, showName: false),
      );
    }
    properties.add(
      IterableProperty<String>(
        'tags',
        tags?.map((SemanticsTag tag) => tag.name),
        defaultValue: null,
      ),
    );
    final List<String> actions =
        _actions.keys
            .map<String>(
              (SemanticsAction action) =>
                  '${action.name}${_debugIsActionBlocked(action) ? '🚫️' : ''}',
            )
            .toList()
          ..sort();
    final List<String?> customSemanticsActions = _customSemanticsActions.keys
        .map<String?>((CustomSemanticsAction action) => action.label)
        .toList();
    properties.add(IterableProperty<String>('actions', actions, ifEmpty: null));
    properties.add(
      IterableProperty<String?>('customActions', customSemanticsActions, ifEmpty: null),
    );

    properties.add(IterableProperty<String>('flags', flagsCollection.toStrings(), ifEmpty: null));
    properties.add(FlagProperty('isInvisible', value: isInvisible, ifTrue: 'invisible'));
    properties.add(FlagProperty('isHidden', value: flagsCollection.isHidden, ifTrue: 'HIDDEN'));
    properties.add(StringProperty('identifier', _identifier, defaultValue: ''));
    properties.add(
      DiagnosticsProperty<Object>(
        'traversalParentIdentifier',
        traversalParentIdentifier,
        defaultValue: null,
      ),
    );
    properties.add(
      DiagnosticsProperty<Object>(
        'traversalChildIdentifier',
        traversalChildIdentifier,
        defaultValue: null,
      ),
    );
    properties.add(AttributedStringProperty('label', _attributedLabel));
    properties.add(AttributedStringProperty('value', _attributedValue));
    properties.add(AttributedStringProperty('increasedValue', _attributedIncreasedValue));
    properties.add(AttributedStringProperty('decreasedValue', _attributedDecreasedValue));
    properties.add(AttributedStringProperty('hint', _attributedHint));
    properties.add(StringProperty('tooltip', _tooltip, defaultValue: ''));
    properties.add(
      EnumProperty<TextDirection>('textDirection', _textDirection, defaultValue: null),
    );
    if (_role != SemanticsRole.none) {
      properties.add(EnumProperty<SemanticsRole>('role', _role));
    }
    properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
    if (_textSelection?.isValid ?? false) {
      properties.add(
        MessageProperty('text selection', '[${_textSelection!.start}, ${_textSelection!.end}]'),
      );
    }
    properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
    properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
    properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
    properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
    properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
    properties.add(DoubleProperty('scrollPosition', scrollPosition, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMax', scrollExtentMax, defaultValue: null));
    properties.add(IntProperty('indexInParent', indexInParent, defaultValue: null));
    properties.add(IntProperty('headingLevel', _headingLevel, defaultValue: 0));
    if (_inputType != SemanticsInputType.none) {
      properties.add(EnumProperty<SemanticsInputType>('inputType', _inputType));
    }
    if (validationResult != SemanticsValidationResult.none) {
      properties.add(
        EnumProperty<SemanticsValidationResult>(
          'validationResult',
          validationResult,
          defaultValue: SemanticsValidationResult.none,
        ),
      );
    }
    properties.add(StringProperty('minValue', _minValue, defaultValue: null));
    properties.add(StringProperty('maxValue', _maxValue, defaultValue: null));
  }

  /// Returns a string representation of this node and its descendants.
  ///
  /// The order in which the children of the [SemanticsNode] will be printed is
  /// controlled by the [childOrder] parameter.
  @override
  String toStringDeep({
    String prefixLineOne = '',
    String? prefixOtherLines,
    DiagnosticLevel minLevel = DiagnosticLevel.debug,
    DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.traversalOrder,
    int wrapWidth = 65,
  }) {
    return toDiagnosticsNode(childOrder: childOrder).toStringDeep(
      prefixLineOne: prefixLineOne,
      prefixOtherLines: prefixOtherLines,
      minLevel: minLevel,
      wrapWidth: wrapWidth,
    );
  }

  @override
  DiagnosticsNode toDiagnosticsNode({
    String? name,
    DiagnosticsTreeStyle? style = DiagnosticsTreeStyle.sparse,
    DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.traversalOrder,
  }) {
    return _SemanticsDiagnosticableNode(
      name: name,
      value: this,
      style: style,
      childOrder: childOrder,
    );
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren({
    DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.traversalOrder,
  }) {
    return debugListChildrenInOrder(childOrder)
        .map<DiagnosticsNode>(
          (SemanticsNode node) => node.toDiagnosticsNode(childOrder: childOrder),
        )
        .toList();
  }

  /// Returns the list of direct children of this node in the specified order.
  List<SemanticsNode> debugListChildrenInOrder(DebugSemanticsDumpOrder childOrder) {
    if (_children == null) {
      return const <SemanticsNode>[];
    }

    return switch (childOrder) {
      DebugSemanticsDumpOrder.inverseHitTest => _children!,
      DebugSemanticsDumpOrder.traversalOrder => _childrenInTraversalOrder(),
    };
  }
}

/// An edge of a box, such as top, bottom, left or right, used to compute
/// [SemanticsNode]s that overlap vertically or horizontally.
///
/// For computing horizontal overlap in an LTR setting we create two [_BoxEdge]
/// objects for each [SemanticsNode]: one representing the left edge (marked
/// with [isLeadingEdge] equal to true) and one for the right edge (with [isLeadingEdge]
/// equal to false). Similarly, for vertical overlap we also create two objects
/// for each [SemanticsNode], one for the top and one for the bottom edge.
class _BoxEdge implements Comparable<_BoxEdge> {
  _BoxEdge({required this.isLeadingEdge, required this.offset, required this.node})
    : assert(offset.isFinite);

  /// True if the edge comes before the seconds edge along the traversal
  /// direction, and false otherwise.
  ///
  /// This field is never null.
  ///
  /// For example, in LTR traversal the left edge's [isLeadingEdge] is set to true,
  /// the right edge's [isLeadingEdge] is set to false. When considering vertical
  /// ordering of boxes, the top edge is the start edge, and the bottom edge is
  /// the end edge.
  final bool isLeadingEdge;

  /// The offset from the start edge of the parent [SemanticsNode] in the
  /// direction of the traversal.
  final double offset;

  /// The node whom this edge belongs.
  final SemanticsNode node;

  @override
  int compareTo(_BoxEdge other) {
    return offset.compareTo(other.offset);
  }
}

/// A group of [nodes] that are disjoint vertically or horizontally from other
/// nodes that share the same [SemanticsNode] parent.
///
/// The [nodes] are sorted among each other separately from other nodes.
class _SemanticsSortGroup implements Comparable<_SemanticsSortGroup> {
  _SemanticsSortGroup({required this.startOffset, required this.textDirection});

  /// The offset from the start edge of the parent [SemanticsNode] in the
  /// direction of the traversal.
  ///
  /// This value is equal to the [_BoxEdge.offset] of the first node in the
  /// [nodes] list being considered.
  final double startOffset;

  final TextDirection textDirection;

  /// The nodes that are sorted among each other.
  final List<SemanticsNode> nodes = <SemanticsNode>[];

  @override
  int compareTo(_SemanticsSortGroup other) {
    return startOffset.compareTo(other.startOffset);
  }

  /// Sorts this group assuming that [nodes] belong to the same vertical group.
  ///
  /// This method breaks up this group into horizontal [_SemanticsSortGroup]s
  /// then sorts them using [sortedWithinKnot].
  List<SemanticsNode> sortedWithinVerticalGroup() {
    final edges = <_BoxEdge>[];
    for (final SemanticsNode child in nodes) {
      // Using a small delta to shrink child rects removes overlapping cases.
      final Rect childRect = child.rect.deflate(0.1);
      edges.add(
        _BoxEdge(
          isLeadingEdge: true,
          offset: _pointInParentCoordinates(child, childRect.topLeft).dx,
          node: child,
        ),
      );
      edges.add(
        _BoxEdge(
          isLeadingEdge: false,
          offset: _pointInParentCoordinates(child, childRect.bottomRight).dx,
          node: child,
        ),
      );
    }
    edges.sort();

    var horizontalGroups = <_SemanticsSortGroup>[];
    _SemanticsSortGroup? group;
    var depth = 0;
    for (final edge in edges) {
      if (edge.isLeadingEdge) {
        depth += 1;
        group ??= _SemanticsSortGroup(startOffset: edge.offset, textDirection: textDirection);
        group.nodes.add(edge.node);
      } else {
        depth -= 1;
      }
      if (depth == 0) {
        horizontalGroups.add(group!);
        group = null;
      }
    }
    horizontalGroups.sort();

    if (textDirection == TextDirection.rtl) {
      horizontalGroups = horizontalGroups.reversed.toList();
    }

    return horizontalGroups
        .expand((_SemanticsSortGroup group) => group.sortedWithinKnot())
        .toList();
  }

  /// Sorts [nodes] where nodes intersect both vertically and horizontally.
  ///
  /// In the special case when [nodes] contains one or less nodes, this method
  /// returns [nodes] unchanged.
  ///
  /// This method constructs a graph, where vertices are [SemanticsNode]s and
  /// edges are "traversed before" relation between pairs of nodes. The sort
  /// order is the topological sorting of the graph, with the original order of
  /// [nodes] used as the tie breaker.
  ///
  /// Whether a node is traversed before another node is determined by the
  /// vector that connects the two nodes' centers. If the vector "points to the
  /// right or down", defined as the [Offset.direction] being between `-pi/4`
  /// and `3*pi/4`), then the semantics node whose center is at the end of the
  /// vector is said to be traversed after.
  List<SemanticsNode> sortedWithinKnot() {
    if (nodes.length <= 1) {
      // Trivial knot. Nothing to do.
      return nodes;
    }
    final nodeMap = <int, SemanticsNode>{};
    final edges = <int, int>{};
    for (final SemanticsNode node in nodes) {
      nodeMap[node.id] = node;
      final Offset center = _pointInParentCoordinates(node, node.rect.center);
      for (final SemanticsNode nextNode in nodes) {
        if (identical(node, nextNode) || edges[nextNode.id] == node.id) {
          // Skip self or when we've already established that the next node
          // points to current node.
          continue;
        }

        final Offset nextCenter = _pointInParentCoordinates(nextNode, nextNode.rect.center);
        final Offset centerDelta = nextCenter - center;
        // When centers coincide, direction is 0.0.
        final double direction = centerDelta.direction;
        final bool isLtrAndForward =
            textDirection == TextDirection.ltr &&
            -math.pi / 4 < direction &&
            direction < 3 * math.pi / 4;
        final bool isRtlAndForward =
            textDirection == TextDirection.rtl &&
            (direction < -3 * math.pi / 4 || direction > 3 * math.pi / 4);
        if (isLtrAndForward || isRtlAndForward) {
          edges[node.id] = nextNode.id;
        }
      }
    }

    final sortedIds = <int>[];
    final visitedIds = <int>{};
    final List<SemanticsNode> startNodes = nodes.toList()
      ..sort((SemanticsNode a, SemanticsNode b) {
        final Offset aTopLeft = _pointInParentCoordinates(a, a.rect.topLeft);
        final Offset bTopLeft = _pointInParentCoordinates(b, b.rect.topLeft);
        final int verticalDiff = aTopLeft.dy.compareTo(bTopLeft.dy);
        if (verticalDiff != 0) {
          return -verticalDiff;
        }
        return -aTopLeft.dx.compareTo(bTopLeft.dx);
      });

    void search(int id) {
      if (visitedIds.contains(id)) {
        return;
      }
      visitedIds.add(id);
      if (edges.containsKey(id)) {
        search(edges[id]!);
      }
      sortedIds.add(id);
    }

    startNodes.map<int>((SemanticsNode node) => node.id).forEach(search);
    return sortedIds.map<SemanticsNode>((int id) => nodeMap[id]!).toList().reversed.toList();
  }
}

/// Converts `point` to the `node`'s parent's coordinate system.
Offset _pointInParentCoordinates(SemanticsNode node, Offset point) {
  final Matrix4? traversalTransform = node._traversalTransform;
  if (traversalTransform == null) {
    return point;
  }
  final vector = Vector3(point.dx, point.dy, 0.0);

  traversalTransform.transform3(vector);
  return Offset(vector.x, vector.y);
}

/// Sorts `children` using the default sorting algorithm, and returns them as a
/// new list.
///
/// The algorithm first breaks up children into groups such that no two nodes
/// from different groups overlap vertically. These groups are sorted vertically
/// according to their [_SemanticsSortGroup.startOffset].
///
/// Within each group, the nodes are sorted using
/// [_SemanticsSortGroup.sortedWithinVerticalGroup].
///
/// For an illustration of the algorithm see http://bit.ly/flutter-default-traversal.
List<SemanticsNode> _childrenInDefaultOrder(
  List<SemanticsNode> children,
  TextDirection textDirection,
) {
  final edges = <_BoxEdge>[];
  for (final child in children) {
    assert(child.rect.isFinite);
    // Using a small delta to shrink child rects removes overlapping cases.
    final Rect childRect = child.rect.deflate(0.1);
    edges.add(
      _BoxEdge(
        isLeadingEdge: true,
        offset: _pointInParentCoordinates(child, childRect.topLeft).dy,
        node: child,
      ),
    );
    edges.add(
      _BoxEdge(
        isLeadingEdge: false,
        offset: _pointInParentCoordinates(child, childRect.bottomRight).dy,
        node: child,
      ),
    );
  }
  edges.sort();

  final verticalGroups = <_SemanticsSortGroup>[];
  _SemanticsSortGroup? group;
  var depth = 0;
  for (final edge in edges) {
    if (edge.isLeadingEdge) {
      depth += 1;
      group ??= _SemanticsSortGroup(startOffset: edge.offset, textDirection: textDirection);
      group.nodes.add(edge.node);
    } else {
      depth -= 1;
    }
    if (depth == 0) {
      verticalGroups.add(group!);
      group = null;
    }
  }
  verticalGroups.sort();

  return verticalGroups
      .expand((_SemanticsSortGroup group) => group.sortedWithinVerticalGroup())
      .toList();
}

/// The implementation of [Comparable] that implements the ordering of
/// [SemanticsNode]s in the accessibility traversal.
///
/// [SemanticsNode]s are sorted prior to sending them to the engine side.
///
/// This implementation considers a [node]'s [sortKey] and its position within
/// the list of its siblings. [sortKey] takes precedence over position.
class _TraversalSortNode implements Comparable<_TraversalSortNode> {
  _TraversalSortNode({required this.node, this.sortKey, required this.position});

  /// The node whose position this sort node determines.
  final SemanticsNode node;

  /// Determines the position of this node among its siblings.
  ///
  /// Sort keys take precedence over other attributes, such as
  /// [position].
  final SemanticsSortKey? sortKey;

  /// Position within the list of siblings as determined by the default sort
  /// order.
  final int position;

  @override
  int compareTo(_TraversalSortNode other) {
    if (sortKey == null || other.sortKey == null) {
      return position - other.position;
    }
    return sortKey!.compareTo(other.sortKey!);
  }
}

/// Owns [SemanticsNode] objects and notifies listeners of changes to the
/// render tree semantics.
///
/// To listen for semantic updates, call [SemanticsBinding.ensureSemantics] or
/// [PipelineOwner.ensureSemantics] to obtain a [SemanticsHandle]. This will
/// create a [SemanticsOwner] if necessary.
class SemanticsOwner extends ChangeNotifier {
  /// Creates a [SemanticsOwner] that manages zero or more [SemanticsNode] objects.
  SemanticsOwner({required this.onSemanticsUpdate}) {
    assert(debugMaybeDispatchCreated('semantics', 'SemanticsOwner', this));
  }

  /// The [onSemanticsUpdate] callback is expected to dispatch [SemanticsUpdate]s
  /// to the [FlutterView] that is associated with this [PipelineOwner] and/or
  /// [SemanticsOwner].
  ///
  /// A [SemanticsOwner] calls [onSemanticsUpdate] during [sendSemanticsUpdate]
  /// after the [SemanticsUpdate] has been build, but before the [SemanticsOwner]'s
  /// listeners have been notified.
  final SemanticsUpdateCallback onSemanticsUpdate;
  final Set<SemanticsNode> _dirtyNodes = <SemanticsNode>{};
  final Map<int, SemanticsNode> _nodes = <int, SemanticsNode>{};
  final Set<SemanticsNode> _detachedNodes = <SemanticsNode>{};
  final Map<Object, SemanticsNode> _traversalParentNodes = <Object, SemanticsNode>{};
  final Map<Object, Set<SemanticsNode>> _traversalChildNodes = <Object, Set<SemanticsNode>>{};

  /// The root node of the semantics tree, if any.
  ///
  /// If the semantics tree is empty, returns null.
  SemanticsNode? get rootSemanticsNode => _nodes[0];

  @override
  void dispose() {
    assert(debugMaybeDispatchDisposed(this));
    _dirtyNodes.clear();
    _nodes.clear();
    _detachedNodes.clear();
    _traversalChildNodes.clear();
    _traversalParentNodes.clear();
    super.dispose();
  }

  /// Update the semantics using [onSemanticsUpdate].
  void sendSemanticsUpdate() {
    // Once the tree is up-to-date, verify that every node is visible.
    assert(() {
      final invisibleNodes = <SemanticsNode>[];
      // Finds the invisible nodes in the tree rooted at `node` and adds them to
      // the invisibleNodes list. If a node is itself invisible, all its
      // descendants will be skipped.
      bool findInvisibleNodes(SemanticsNode node) {
        if (node.rect.isEmpty) {
          invisibleNodes.add(node);
        } else if (!node.mergeAllDescendantsIntoThisNode) {
          node.visitChildren(findInvisibleNodes);
        }
        return true;
      }

      final SemanticsNode? rootSemanticsNode = this.rootSemanticsNode;
      if (rootSemanticsNode != null) {
        // The root node is allowed to be invisible when it has no children.
        if (rootSemanticsNode.childrenCount > 0 && rootSemanticsNode.rect.isEmpty) {
          invisibleNodes.add(rootSemanticsNode);
        } else if (!rootSemanticsNode.mergeAllDescendantsIntoThisNode) {
          rootSemanticsNode.visitChildren(findInvisibleNodes);
        }
      }

      if (invisibleNodes.isEmpty) {
        return true;
      }

      List<DiagnosticsNode> nodeToMessage(SemanticsNode invisibleNode) {
        final SemanticsNode? parent = invisibleNode.parent;
        return <DiagnosticsNode>[
          invisibleNode.toDiagnosticsNode(style: DiagnosticsTreeStyle.errorProperty),
          parent?.toDiagnosticsNode(
                name: 'which was added as a child of',
                style: DiagnosticsTreeStyle.errorProperty,
              ) ??
              ErrorDescription('which was added as the root SemanticsNode'),
        ];
      }

      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Invisible SemanticsNodes should not be added to the tree.'),
        ErrorDescription('The following invisible SemanticsNodes were added to the tree:'),
        ...invisibleNodes.expand(nodeToMessage),
        ErrorHint(
          'An invisible SemanticsNode is one whose rect is not on screen hence not reachable for users, '
          'and its semantic information is not merged into a visible parent.',
        ),
        ErrorHint(
          'An invisible SemanticsNode makes the accessibility experience confusing, '
          'as it does not provide any visual indication when the user selects it '
          'via accessibility technologies.',
        ),
        ErrorHint(
          'Consider removing the above invisible SemanticsNodes if they were added by your '
          'RenderObject.assembleSemanticsNode implementation, or filing a bug on GitHub:\n'
          '  https://github.com/flutter/flutter/issues/new?template=02_bug.yml',
        ),
      ]);
    }());

    if (_dirtyNodes.isEmpty) {
      return;
    }
    final customSemanticsActionIds = <int>{};
    final visitedNodes = <SemanticsNode>[];
    while (_dirtyNodes.isNotEmpty) {
      final List<SemanticsNode> localDirtyNodes = _dirtyNodes
          .where((SemanticsNode node) => !_detachedNodes.contains(node))
          .toList();
      _dirtyNodes.clear();
      _detachedNodes.clear();
      localDirtyNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
      visitedNodes.addAll(localDirtyNodes);
      for (final node in localDirtyNodes) {
        assert(node._dirty);
        assert(node.parent == null || !node.parent!.isPartOfNodeMerging || node.isMergedIntoParent);
        if (node.isPartOfNodeMerging) {
          assert(node.mergeAllDescendantsIntoThisNode || node.parent != null);
          // If child node is merged into its parent, make sure the parent is marked as dirty
          if (node.parent != null && node.parent!.isPartOfNodeMerging) {
            node.parent!._markDirty(); // this can add the node to the dirty list
            node._dirty = false; // Do not send update for this node, as it's now part of its parent
          }
        }

        // Clean up the dirty entry in owner._traversalParentNodes map because it
        // will be updated later.
        _traversalParentNodes.removeWhere((Object key, SemanticsNode oldNode) => node == oldNode);
        // Clean up the node from the value set in owner._traversalChildNodes.
        for (final Set<SemanticsNode> childSet in _traversalChildNodes.values) {
          childSet.removeWhere((SemanticsNode oldNode) => node == oldNode);
        }
      }
    }

    visitedNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
    final SemanticsUpdateBuilder builder = SemanticsBinding.instance.createSemanticsUpdateBuilder();

    final updatedVisitedNodes = <SemanticsNode>[];

    for (final node in visitedNodes) {
      final bool isTraversalParent = node._isTraversalParent;
      final bool isTraversalChild = node._isTraversalChild;

      if (kIsWeb) {
        updatedVisitedNodes.add(node);
      } else {
        if (!isTraversalParent && !isTraversalChild) {
          updatedVisitedNodes.add(node);
          continue;
        }

        if (isTraversalChild) {
          // If the node has a non-null `_traversalChildIdentifier`, it indicates
          // that its hit-test parent and traversal parent are different, and
          // its traversal parent should update its children to include this node.
          // Therefore, its traversal parent node should be added to the
          // `updatedVisitedNodes` list for later grafting, in order to generate
          // a correct `childrenIntraversalOrder`. This is typically used in
          // `OverlayPortal` widget.
          final SemanticsNode? parentNode = _traversalParentNodes[node.traversalChildIdentifier];
          if (parentNode != null && !updatedVisitedNodes.contains(parentNode)) {
            updatedVisitedNodes.add(parentNode);
          }
        }

        updatedVisitedNodes.add(node);
      }

      // If the node is a traversal parent, then add it to the
      // _traversalParentNodes map for later grafting. Similarly, add the node
      // to the _traversalChildNodes map if it is a traversal child.
      if (isTraversalParent) {
        assert(
          !_traversalParentNodes.containsKey(node._traversalParentIdentifier) ||
              _traversalParentNodes[node.traversalParentIdentifier!] == node,
          'The traversalParentIdentifier must be unique. No two semantics nodes can share the same traversalParentIdentifier.',
        );
        _traversalParentNodes[node.traversalParentIdentifier!] = node;
      } else if (isTraversalChild) {
        _traversalChildNodes[node.traversalChildIdentifier!] ??= <SemanticsNode>{};
        _traversalChildNodes[node.traversalChildIdentifier!]!.add(node);
      }
    }

    for (final node in updatedVisitedNodes) {
      assert(
        node.parent?._dirty != true || node._isTraversalParent,
      ); // could be null (no parent) or false (not dirty)

      // The traversalParentNode is added to updatedVisitedNodes for later
      // grafting; its traversalChildren should be grafted to its children in
      // the traversal order. This grafting process is skipped on web because
      // the traversal order will be handled in the web engine.
      final bool needUpdateTraversalParent = !kIsWeb && node._isTraversalParent;
      // The _serialize() method marks the node as not dirty, and
      // recurses through the tree to do a deep serialization of all
      // contiguous dirty nodes. This means that when we return here,
      // it's quite possible that subsequent nodes are no longer
      // dirty. We skip these here.
      // We also skip any nodes that were reset and subsequently
      // dropped entirely (RenderObject.markNeedsSemanticsUpdate()
      // calls reset() on its SemanticsNode if onlyChanges isn't set,
      // which happens e.g. when the node is no longer contributing
      // semantics).
      if ((node._dirty || needUpdateTraversalParent) && node.attached) {
        node._addToUpdate(builder, customSemanticsActionIds);
      }
    }
    _dirtyNodes.clear();
    for (final actionId in customSemanticsActionIds) {
      final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId)!;
      builder.updateCustomAction(
        id: actionId,
        label: action.label,
        hint: action.hint,
        overrideId: action.action?.index ?? -1,
      );
    }
    onSemanticsUpdate(builder.build());
    notifyListeners();
  }

  SemanticsActionHandler? _getSemanticsActionHandlerForId(int id, SemanticsAction action) {
    SemanticsNode? result = _nodes[id];
    if (result != null && result.isPartOfNodeMerging && !result._canPerformAction(action)) {
      result._visitDescendants((SemanticsNode node) {
        if (node._canPerformAction(action)) {
          result = node;
          return false; // found node, abort walk
        }
        return true; // continue walk
      });
    }
    if (result == null || !result!._canPerformAction(action)) {
      return null;
    }
    return result!._actions[action];
  }

  /// Asks the [SemanticsNode] with the given id to perform the given action.
  ///
  /// If the [SemanticsNode] has not indicated that it can perform the action,
  /// this function does nothing.
  ///
  /// If the given `action` requires arguments they need to be passed in via
  /// the `args` parameter.
  void performAction(int id, SemanticsAction action, [Object? args]) {
    final SemanticsActionHandler? handler = _getSemanticsActionHandlerForId(id, action);
    if (handler != null) {
      handler(args);
      return;
    }

    // Default actions if no [handler] was provided.
    if (action == SemanticsAction.showOnScreen && _nodes[id]?._showOnScreen != null) {
      _nodes[id]!._showOnScreen!();
    }
  }

  SemanticsActionHandler? _getSemanticsActionHandlerForPosition(
    SemanticsNode node,
    Offset position,
    SemanticsAction action,
  ) {
    if (node.transform != null) {
      final inverse = Matrix4.identity();
      if (inverse.copyInverse(node.transform!) == 0.0) {
        return null;
      }
      position = MatrixUtils.transformPoint(inverse, position);
    }
    if (!node.rect.contains(position)) {
      return null;
    }
    if (node.mergeAllDescendantsIntoThisNode) {
      if (node._canPerformAction(action)) {
        return node._actions[action];
      }
      SemanticsNode? result;
      node._visitDescendants((SemanticsNode child) {
        if (child._canPerformAction(action)) {
          result = child;
          return false;
        }
        return true;
      });
      return result?._actions[action];
    }
    if (node.hasChildren) {
      for (final SemanticsNode child in node._children!.reversed) {
        final SemanticsActionHandler? handler = _getSemanticsActionHandlerForPosition(
          child,
          position,
          action,
        );
        if (handler != null) {
          return handler;
        }
      }
    }
    return node._actions[action];
  }

  /// Asks the [SemanticsNode] at the given position to perform the given action.
  ///
  /// If the [SemanticsNode] has not indicated that it can perform the action,
  /// this function does nothing.
  ///
  /// If the given `action` requires arguments they need to be passed in via
  /// the `args` parameter.
  void performActionAt(Offset position, SemanticsAction action, [Object? args]) {
    final SemanticsNode? node = rootSemanticsNode;
    if (node == null) {
      return;
    }
    final SemanticsActionHandler? handler = _getSemanticsActionHandlerForPosition(
      node,
      position,
      action,
    );
    if (handler != null) {
      handler(args);
    }
  }

  @override
  String toString() => describeIdentity(this);
}

/// Describes the semantic information associated with the owning
/// [RenderObject].
///
/// The information provided in the configuration is used to generate the
/// semantics tree.
class SemanticsConfiguration {
  // SEMANTIC BOUNDARY BEHAVIOR

  /// Whether the [RenderObject] owner of this configuration wants to own its
  /// own [SemanticsNode].
  ///
  /// When set to true semantic information associated with the [RenderObject]
  /// owner of this configuration or any of its descendants will not leak into
  /// parents. The [SemanticsNode] generated out of this configuration will
  /// act as a boundary.
  ///
  /// Whether descendants of the owning [RenderObject] can add their semantic
  /// information to the [SemanticsNode] introduced by this configuration
  /// is controlled by [explicitChildNodes].
  ///
  /// This has to be true if [isMergingSemanticsOfDescendants] is also true.
  bool get isSemanticBoundary => _isSemanticBoundary;
  bool _isSemanticBoundary = false;
  set isSemanticBoundary(bool value) {
    assert(!isMergingSemanticsOfDescendants || value);
    _isSemanticBoundary = value;
  }

  /// The locale for widgets in the subtree.
  Locale? get localeForSubtree => _localeForSubtree;
  Locale? _localeForSubtree;
  set localeForSubtree(Locale? value) {
    assert(value != null);
    _localeForSubtree = value;
    _hasBeenAnnotated = true;
  }

  /// The locale of the resulting semantics node if this configuration formed
  /// one.
  ///
  /// This is used internally to track the inherited locale from parent
  /// rendering object and should not be used directly.
  ///
  /// To set a locale for a rendering object, use [localeForSubtree] instead.
  Locale? locale;

  /// Whether to block pointer related user actions for the rendering subtree.
  ///
  /// Setting this to true will prevent users from interacting with the
  /// rendering object produces this semantics configuration and its subtree
  /// through pointer-related [SemanticsAction]s in assistive technologies.
  ///
  /// The [SemanticsNode] created from this semantics configuration is still
  /// focusable by assistive technologies. Only pointer-related
  /// [SemanticsAction]s, such as [SemanticsAction.tap] or its friends, are
  /// blocked.
  ///
  /// If this semantics configuration is merged into a parent semantics node,
  /// only the [SemanticsAction]s from this rendering object and the rendering
  /// objects in the subtree are blocked.
  bool isBlockingUserActions = false;

  /// Whether the configuration forces all children of the owning [RenderObject]
  /// that want to contribute semantic information to the semantics tree to do
  /// so in the form of explicit [SemanticsNode]s.
  ///
  /// When set to false children of the owning [RenderObject] are allowed to
  /// annotate [SemanticsNode]s of their parent with the semantic information
  /// they want to contribute to the semantic tree.
  /// When set to true the only way for children of the owning [RenderObject]
  /// to contribute semantic information to the semantic tree is to introduce
  /// new explicit [SemanticsNode]s to the tree.
  ///
  /// This setting is often used in combination with [isSemanticBoundary] to
  /// create semantic boundaries that are either writable or not for children.
  bool explicitChildNodes = false;

  /// Whether the owning [RenderObject] makes other [RenderObject]s previously
  /// painted within the same semantic boundary unreachable for accessibility
  /// purposes.
  ///
  /// If set to true, the semantic information for all siblings and cousins of
  /// this node, that are earlier in a depth-first pre-order traversal, are
  /// dropped from the semantics tree up until a semantic boundary (as defined
  /// by [isSemanticBoundary]) is reached.
  ///
  /// If [isSemanticBoundary] and [isBlockingSemanticsOfPreviouslyPaintedNodes]
  /// is set on the same node, all previously painted siblings and cousins up
  /// until the next ancestor that is a semantic boundary are dropped.
  ///
  /// Paint order as established by [RenderObject.visitChildrenForSemantics] is
  /// used to determine if a node is previous to this one.
  bool isBlockingSemanticsOfPreviouslyPaintedNodes = false;

  // SEMANTIC ANNOTATIONS
  // These will end up on [SemanticsNode]s generated from
  // [SemanticsConfiguration]s.

  /// Whether this configuration is empty.
  ///
  /// An empty configuration doesn't contain any semantic information that it
  /// wants to contribute to the semantics tree.
  bool get hasBeenAnnotated => _hasBeenAnnotated;
  bool _hasBeenAnnotated = false;

  /// The actions (with associated action handlers) that this configuration
  /// would like to contribute to the semantics tree.
  ///
  /// See also:
  ///
  ///  * [_addAction] to add an action.
  final Map<SemanticsAction, SemanticsActionHandler> _actions =
      <SemanticsAction, SemanticsActionHandler>{};

  int get _effectiveActionsAsBits =>
      isBlockingUserActions ? _actionsAsBits & _kUnblockedUserActions : _actionsAsBits;
  int _actionsAsBits = 0;

  /// Adds an `action` to the semantics tree.
  ///
  /// The provided `handler` is called to respond to the user triggered
  /// `action`.
  void _addAction(SemanticsAction action, SemanticsActionHandler handler) {
    _actions[action] = handler;
    _actionsAsBits |= action.index;
    _hasBeenAnnotated = true;
  }

  /// Adds an `action` to the semantics tree, whose `handler` does not expect
  /// any arguments.
  ///
  /// The provided `handler` is called to respond to the user triggered
  /// `action`.
  void _addArgumentlessAction(SemanticsAction action, VoidCallback handler) {
    _addAction(action, (Object? args) {
      assert(args == null);
      handler();
    });
  }

  /// The handler for [SemanticsAction.tap].
  ///
  /// This is the semantic equivalent of a user briefly tapping the screen with
  /// the finger without moving it. For example, a button should implement this
  /// action.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen while an element is focused.
  ///
  /// On Android prior to Android Oreo a double-tap on the screen while an
  /// element with an [onTap] handler is focused will not call the registered
  /// handler. Instead, Android will simulate a pointer down and up event at the
  /// center of the focused element. Those pointer events will get dispatched
  /// just like a regular tap with TalkBack disabled would: The events will get
  /// processed by any [GestureDetector] listening for gestures in the center of
  /// the focused element. Therefore, to ensure that [onTap] handlers work
  /// properly on Android versions prior to Oreo, a [GestureDetector] with an
  /// onTap handler should always be wrapping an element that defines a
  /// semantic [onTap] handler. By default a [GestureDetector] will register its
  /// own semantic [onTap] handler that follows this principle.
  VoidCallback? get onTap => _onTap;
  VoidCallback? _onTap;
  set onTap(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.tap, value!);
    _onTap = value;
  }

  /// The handler for [SemanticsAction.longPress].
  ///
  /// This is the semantic equivalent of a user pressing and holding the screen
  /// with the finger for a few seconds without moving it.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen without lifting the finger after the
  /// second tap.
  VoidCallback? get onLongPress => _onLongPress;
  VoidCallback? _onLongPress;
  set onLongPress(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.longPress, value!);
    _onLongPress = value;
  }

  /// The handler for [SemanticsAction.scrollLeft].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from right to left. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping left with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollLeft => _onScrollLeft;
  VoidCallback? _onScrollLeft;
  set onScrollLeft(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollLeft, value!);
    _onScrollLeft = value;
  }

  /// The handler for [SemanticsAction.dismiss].
  ///
  /// This is a request to dismiss the currently focused node.
  ///
  /// TalkBack users on Android can trigger this action in the local context
  /// menu, and VoiceOver users on iOS can trigger this action with a standard
  /// gesture or menu option.
  VoidCallback? get onDismiss => _onDismiss;
  VoidCallback? _onDismiss;
  set onDismiss(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.dismiss, value!);
    _onDismiss = value;
  }

  /// The handler for [SemanticsAction.scrollRight].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from left to right. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping right with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollRight => _onScrollRight;
  VoidCallback? _onScrollRight;
  set onScrollRight(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollRight, value!);
    _onScrollRight = value;
  }

  /// The handler for [SemanticsAction.scrollUp].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from bottom to top. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollUp => _onScrollUp;
  VoidCallback? _onScrollUp;
  set onScrollUp(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollUp, value!);
    _onScrollUp = value;
  }

  /// The handler for [SemanticsAction.scrollDown].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from top to bottom. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback? get onScrollDown => _onScrollDown;
  VoidCallback? _onScrollDown;
  set onScrollDown(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.scrollDown, value!);
    _onScrollDown = value;
  }

  /// The handler for [SemanticsAction.scrollToOffset].
  ///
  /// This handler is only called on iOS by UIKit, when the iOS focus engine
  /// switches its focus to an item too close to a scrollable edge of a
  /// scrollable container, to make sure the focused item is always fully
  /// visible.
  ///
  /// The callback, if not `null`, should typically set the scroll offset of
  /// the associated scrollable container to the given `targetOffset` without
  /// animation as it is already animated by the caller: the iOS focus engine
  /// invokes [onScrollToOffset] every frame during the scroll animation with
  /// animated scroll offset values.
  ScrollToOffsetHandler? get onScrollToOffset => _onScrollToOffset;
  ScrollToOffsetHandler? _onScrollToOffset;
  set onScrollToOffset(ScrollToOffsetHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.scrollToOffset, (Object? args) {
      final list = args! as Float64List;
      value!(Offset(list[0], list[1]));
    });
    _onScrollToOffset = value;
  }

  /// The handler for [SemanticsAction.increase].
  ///
  /// This is a request to increase the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If [value] is set, [increasedValue] must also be provided and
  /// [onIncrease] must ensure that [value] will be set to [increasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume up button.
  VoidCallback? get onIncrease => _onIncrease;
  VoidCallback? _onIncrease;
  set onIncrease(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.increase, value!);
    _onIncrease = value;
  }

  /// The handler for [SemanticsAction.decrease].
  ///
  /// This is a request to decrease the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If [value] is set, [decreasedValue] must also be provided and
  /// [onDecrease] must ensure that [value] will be set to [decreasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume down button.
  VoidCallback? get onDecrease => _onDecrease;
  VoidCallback? _onDecrease;
  set onDecrease(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.decrease, value!);
    _onDecrease = value;
  }

  /// The handler for [SemanticsAction.copy].
  ///
  /// This is a request to copy the current selection to the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback? get onCopy => _onCopy;
  VoidCallback? _onCopy;
  set onCopy(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.copy, value!);
    _onCopy = value;
  }

  /// The handler for [SemanticsAction.cut].
  ///
  /// This is a request to cut the current selection and place it in the
  /// clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback? get onCut => _onCut;
  VoidCallback? _onCut;
  set onCut(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.cut, value!);
    _onCut = value;
  }

  /// The handler for [SemanticsAction.paste].
  ///
  /// This is a request to paste the current content of the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback? get onPaste => _onPaste;
  VoidCallback? _onPaste;
  set onPaste(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.paste, value!);
    _onPaste = value;
  }

  /// The handler for [SemanticsAction.showOnScreen].
  ///
  /// A request to fully show the semantics node on screen. For example, this
  /// action might be send to a node in a scrollable list that is partially off
  /// screen to bring it on screen.
  ///
  /// For elements in a scrollable list the framework provides a default
  /// implementation for this action and it is not advised to provide a
  /// custom one via this setter.
  VoidCallback? get onShowOnScreen => _onShowOnScreen;
  VoidCallback? _onShowOnScreen;
  set onShowOnScreen(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.showOnScreen, value!);
    _onShowOnScreen = value;
  }

  /// The handler for [SemanticsAction.moveCursorForwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field forward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume up key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorForwardByCharacter => _onMoveCursorForwardByCharacter;
  MoveCursorHandler? _onMoveCursorForwardByCharacter;
  set onMoveCursorForwardByCharacter(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorForwardByCharacter, (Object? args) {
      final extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorForwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.moveCursorBackwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorBackwardByCharacter => _onMoveCursorBackwardByCharacter;
  MoveCursorHandler? _onMoveCursorBackwardByCharacter;
  set onMoveCursorBackwardByCharacter(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorBackwardByCharacter, (Object? args) {
      final extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorBackwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.moveCursorForwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorForwardByWord => _onMoveCursorForwardByWord;
  MoveCursorHandler? _onMoveCursorForwardByWord;
  set onMoveCursorForwardByWord(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorForwardByWord, (Object? args) {
      final extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorForwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.moveCursorBackwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler? get onMoveCursorBackwardByWord => _onMoveCursorBackwardByWord;
  MoveCursorHandler? _onMoveCursorBackwardByWord;
  set onMoveCursorBackwardByWord(MoveCursorHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorBackwardByWord, (Object? args) {
      final extendSelection = args! as bool;
      value!(extendSelection);
    });
    _onMoveCursorBackwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.setSelection].
  ///
  /// This handler is invoked when the user either wants to change the currently
  /// selected text in a text field or change the position of the cursor.
  ///
  /// TalkBack users can trigger this handler by selecting "Move cursor to
  /// beginning/end" or "Select all" from the local context menu.
  SetSelectionHandler? get onSetSelection => _onSetSelection;
  SetSelectionHandler? _onSetSelection;
  set onSetSelection(SetSelectionHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.setSelection, (Object? args) {
      assert(args != null && args is Map);
      final Map<String, int> selection = (args! as Map<dynamic, dynamic>).cast<String, int>();
      assert(selection['base'] != null && selection['extent'] != null);
      value!(TextSelection(baseOffset: selection['base']!, extentOffset: selection['extent']!));
    });
    _onSetSelection = value;
  }

  /// The handler for [SemanticsAction.setText].
  ///
  /// This handler is invoked when the user wants to replace the current text in
  /// the text field with a new text.
  ///
  /// Voice access users can trigger this handler by speaking `type <text>` to
  /// their Android devices.
  SetTextHandler? get onSetText => _onSetText;
  SetTextHandler? _onSetText;
  set onSetText(SetTextHandler? value) {
    assert(value != null);
    _addAction(SemanticsAction.setText, (Object? args) {
      assert(args != null && args is String);
      final text = args! as String;
      value!(text);
    });
    _onSetText = value;
  }

  /// The handler for [SemanticsAction.didGainAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler gains
  /// the accessibility focus. The accessibility focus is the
  /// green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidLoseAccessibilityFocus], which is invoked when the accessibility
  ///    focus is removed from the node.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  VoidCallback? get onDidGainAccessibilityFocus => _onDidGainAccessibilityFocus;
  VoidCallback? _onDidGainAccessibilityFocus;
  set onDidGainAccessibilityFocus(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.didGainAccessibilityFocus, value!);
    _onDidGainAccessibilityFocus = value;
  }

  /// The handler for [SemanticsAction.didLoseAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler
  /// loses the accessibility focus. The accessibility focus is
  /// the green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidGainAccessibilityFocus], which is invoked when the node gains
  ///    accessibility focus.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  VoidCallback? get onDidLoseAccessibilityFocus => _onDidLoseAccessibilityFocus;
  VoidCallback? _onDidLoseAccessibilityFocus;
  set onDidLoseAccessibilityFocus(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.didLoseAccessibilityFocus, value!);
    _onDidLoseAccessibilityFocus = value;
  }

  /// {@macro flutter.semantics.SemanticsProperties.onFocus}
  VoidCallback? get onFocus => _onFocus;
  VoidCallback? _onFocus;
  set onFocus(VoidCallback? value) {
    _addArgumentlessAction(SemanticsAction.focus, value!);
    _onFocus = value;
  }

  /// The handler for [SemanticsAction.expand].
  ///
  /// This is a request to expand the currently focused node.
  VoidCallback? get onExpand => _onExpand;
  VoidCallback? _onExpand;
  set onExpand(VoidCallback? value) {
    assert(value != null);
    _addArgumentlessAction(SemanticsAction.expand, value!);
    _onExpand = value;
  }

  /// The handler for [SemanticsAction.collapse].
  ///
  /// This is a request to collapse the currently focused node.
  VoidCallback? get onCollapse => _onCollapse;
  VoidCallback? _onCollapse;
  set onCollapse(VoidCallback? value) {
    assert(value != null);
    _addArgumentlessAction(SemanticsAction.collapse, value!);
    _onCollapse = value;
  }

  /// A delegate that decides how to handle [SemanticsConfiguration]s produced
  /// in the widget subtree.
  ///
  /// The [SemanticsConfiguration]s are produced by rendering objects in the
  /// subtree and want to merge up to their parent. This delegate can decide
  /// which of these should be merged together to form sibling SemanticsNodes and
  /// which of them should be merged upwards into the parent SemanticsNode.
  ///
  /// The input list of [SemanticsConfiguration]s can be empty if the rendering
  /// object of this semantics configuration is a leaf node or child rendering
  /// objects do not contribute to the semantics.
  ChildSemanticsConfigurationsDelegate? get childConfigurationsDelegate =>
      _childConfigurationsDelegate;
  ChildSemanticsConfigurationsDelegate? _childConfigurationsDelegate;
  set childConfigurationsDelegate(ChildSemanticsConfigurationsDelegate? value) {
    assert(value != null);
    _childConfigurationsDelegate = value;
    // Setting the childConfigsDelegate does not annotate any meaningful
    // semantics information of the config.
  }

  /// Returns the action handler registered for [action] or null if none was
  /// registered.
  SemanticsActionHandler? getActionHandler(SemanticsAction action) => _actions[action];

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  ///
  /// Whether this sort key has an effect on the [SemanticsNode] sort order is
  /// subject to how this configuration is used. For example, the [absorb]
  /// method may decide to not use this key when it combines multiple
  /// [SemanticsConfiguration] objects.
  SemanticsSortKey? get sortKey => _sortKey;
  SemanticsSortKey? _sortKey;
  set sortKey(SemanticsSortKey? value) {
    assert(value != null);
    _sortKey = value;
    _hasBeenAnnotated = true;
  }

  /// The index of this node within the parent's list of semantic children.
  ///
  /// This includes all semantic nodes, not just those currently in the
  /// child list. For example, if a scrollable has five children but the first
  /// two are not visible (and thus not included in the list of children), then
  /// the index of the last node will still be 4.
  int? get indexInParent => _indexInParent;
  int? _indexInParent;
  set indexInParent(int? value) {
    _indexInParent = value;
    _hasBeenAnnotated = true;
  }

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  int? get scrollChildCount => _scrollChildCount;
  int? _scrollChildCount;
  set scrollChildCount(int? value) {
    if (value == scrollChildCount) {
      return;
    }
    _scrollChildCount = value;
    _hasBeenAnnotated = true;
  }

  /// The index of the first visible scrollable child that contributes to
  /// semantics.
  int? get scrollIndex => _scrollIndex;
  int? _scrollIndex;
  set scrollIndex(int? value) {
    if (value == scrollIndex) {
      return;
    }
    _scrollIndex = value;
    _hasBeenAnnotated = true;
  }

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  int? get platformViewId => _platformViewId;
  int? _platformViewId;
  set platformViewId(int? value) {
    if (value == platformViewId) {
      return;
    }
    _platformViewId = value;
    _hasBeenAnnotated = true;
  }

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [isTextField] is true. Defaults to null,
  /// which means no limit is imposed on the text field.
  int? get maxValueLength => _maxValueLength;
  int? _maxValueLength;
  set maxValueLength(int? value) {
    if (value == maxValueLength) {
      return;
    }
    _maxValueLength = value;
    _hasBeenAnnotated = true;
  }

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [isTextField] is true. Must be set when
  /// [maxValueLength] is set.
  int? get currentValueLength => _currentValueLength;
  int? _currentValueLength;
  set currentValueLength(int? value) {
    if (value == currentValueLength) {
      return;
    }
    _currentValueLength = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the semantic information provided by the owning [RenderObject] and
  /// all of its descendants should be treated as one logical entity.
  ///
  /// If set to true, the descendants of the owning [RenderObject]'s
  /// [SemanticsNode] will merge their semantic information into the
  /// [SemanticsNode] representing the owning [RenderObject].
  ///
  /// Setting this to true requires that [isSemanticBoundary] is also true.
  bool get isMergingSemanticsOfDescendants => _isMergingSemanticsOfDescendants;
  bool _isMergingSemanticsOfDescendants = false;
  set isMergingSemanticsOfDescendants(bool value) {
    assert(isSemanticBoundary);
    _isMergingSemanticsOfDescendants = value;
    _hasBeenAnnotated = true;
  }

  /// The handlers for each supported [CustomSemanticsAction].
  ///
  /// Whenever a custom accessibility action is added to a node, the action
  /// [SemanticsAction.customAction] is automatically added. A handler is
  /// created which uses the passed argument to lookup the custom action
  /// handler from this map and invoke it, if present.
  Map<CustomSemanticsAction, VoidCallback> get customSemanticsActions => _customSemanticsActions;
  Map<CustomSemanticsAction, VoidCallback> _customSemanticsActions =
      <CustomSemanticsAction, VoidCallback>{};
  set customSemanticsActions(Map<CustomSemanticsAction, VoidCallback> value) {
    _hasBeenAnnotated = true;
    _actionsAsBits |= SemanticsAction.customAction.index;
    _customSemanticsActions = value;
    _actions[SemanticsAction.customAction] = _onCustomSemanticsAction;
  }

  void _onCustomSemanticsAction(Object? args) {
    final CustomSemanticsAction? action = CustomSemanticsAction.getAction(args! as int);
    if (action == null) {
      return;
    }
    final VoidCallback? callback = _customSemanticsActions[action];
    if (callback != null) {
      callback();
    }
  }

  /// {@macro flutter.semantics.SemanticsProperties.identifier}
  String get identifier => _identifier;
  String _identifier = '';
  set identifier(String identifier) {
    _identifier = identifier;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.traversalParentIdentifier}
  Object? get traversalParentIdentifier => _traversalParentIdentifier;
  Object? _traversalParentIdentifier;
  set traversalParentIdentifier(Object? value) {
    if (value == traversalParentIdentifier) {
      return;
    }
    _traversalParentIdentifier = value;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.traversalChildIdentifier}
  Object? get traversalChildIdentifier => _traversalChildIdentifier;
  Object? _traversalChildIdentifier;
  set traversalChildIdentifier(Object? value) {
    if (value == traversalChildIdentifier) {
      return;
    }
    _traversalChildIdentifier = value;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.role}
  SemanticsRole get role => _role;
  SemanticsRole _role = SemanticsRole.none;
  set role(SemanticsRole value) {
    _role = value;
    _hasBeenAnnotated = true;
  }

  /// A textual description of the owning [RenderObject].
  ///
  /// Setting this attribute will override the [attributedLabel].
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedLabel], which is the [AttributedString] of this property.
  String get label => _attributedLabel.string;
  set label(String label) {
    _attributedLabel = AttributedString(label);
    _hasBeenAnnotated = true;
  }

  /// A textual description of the owning [RenderObject] in [AttributedString]
  /// format.
  ///
  /// On iOS this is used for the `accessibilityAttributedLabel` property
  /// defined in the `UIAccessibility` Protocol. On Android it is concatenated
  /// together with [attributedValue] and [attributedHint] in the following
  /// order: [attributedValue], [attributedLabel], [attributedHint]. The
  /// concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [label], which is the raw text of this property.
  AttributedString get attributedLabel => _attributedLabel;
  AttributedString _attributedLabel = AttributedString('');
  set attributedLabel(AttributedString attributedLabel) {
    _attributedLabel = attributedLabel;
    _hasBeenAnnotated = true;
  }

  /// A textual description for the current value of the owning [RenderObject].
  ///
  /// Setting this attribute will override the [attributedValue].
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedValue], which is the [AttributedString] of this property.
  ///  * [increasedValue] and [attributedIncreasedValue], which describe what
  ///    [value] will be after performing [SemanticsAction.increase].
  ///  * [decreasedValue] and [attributedDecreasedValue], which describe what
  ///    [value] will be after performing [SemanticsAction.decrease].
  String get value => _attributedValue.string;
  set value(String value) {
    _attributedValue = AttributedString(value);
    _hasBeenAnnotated = true;
  }

  /// A textual description for the current value of the owning [RenderObject]
  /// in [AttributedString] format.
  ///
  /// On iOS this is used for the `accessibilityAttributedValue` property
  /// defined in the `UIAccessibility` Protocol. On Android it is concatenated
  /// together with [attributedLabel] and [attributedHint] in the following
  /// order: [attributedValue], [attributedLabel], [attributedHint]. The
  /// concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [value], which is the raw text of this property.
  ///  * [attributedIncreasedValue], which describes what [value] will be after
  ///    performing [SemanticsAction.increase].
  ///  * [attributedDecreasedValue], which describes what [value] will be after
  ///    performing [SemanticsAction.decrease].
  AttributedString get attributedValue => _attributedValue;
  AttributedString _attributedValue = AttributedString('');
  set attributedValue(AttributedString attributedValue) {
    _attributedValue = attributedValue;
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.increase] action.
  ///
  /// Setting this attribute will override the [attributedIncreasedValue].
  ///
  /// One of the [attributedIncreasedValue] or [increasedValue] must be set if
  /// a handler for [SemanticsAction.increase] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedIncreasedValue], which is the [AttributedString] of this property.
  String get increasedValue => _attributedIncreasedValue.string;
  set increasedValue(String increasedValue) {
    _attributedIncreasedValue = AttributedString(increasedValue);
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.increase] action in [AttributedString] format.
  ///
  /// One of the [attributedIncreasedValue] or [increasedValue] must be set if
  /// a handler for [SemanticsAction.increase] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [increasedValue], which is the raw text of this property.
  AttributedString get attributedIncreasedValue => _attributedIncreasedValue;
  AttributedString _attributedIncreasedValue = AttributedString('');
  set attributedIncreasedValue(AttributedString attributedIncreasedValue) {
    _attributedIncreasedValue = attributedIncreasedValue;
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.decrease] action.
  ///
  /// Setting this attribute will override the [attributedDecreasedValue].
  ///
  /// One of the [attributedDecreasedValue] or [decreasedValue] must be set if
  /// a handler for [SemanticsAction.decrease] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  ///  * [attributedDecreasedValue], which is the [AttributedString] of this property.
  String get decreasedValue => _attributedDecreasedValue.string;
  set decreasedValue(String decreasedValue) {
    _attributedDecreasedValue = AttributedString(decreasedValue);
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.decrease] action in [AttributedString] format.
  ///
  /// One of the [attributedDecreasedValue] or [decreasedValue] must be set if
  /// a handler for [SemanticsAction.decrease] is provided and one of the
  /// [value] or [attributedValue] is set.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [decreasedValue], which is the raw text of this property.
  AttributedString get attributedDecreasedValue => _attributedDecreasedValue;
  AttributedString _attributedDecreasedValue = AttributedString('');
  set attributedDecreasedValue(AttributedString attributedDecreasedValue) {
    _attributedDecreasedValue = attributedDecreasedValue;
    _hasBeenAnnotated = true;
  }

  /// A brief description of the result of performing an action on this node.
  ///
  /// Setting this attribute will override the [attributedHint].
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [attributedHint], which is the [AttributedString] of this property.
  String get hint => _attributedHint.string;
  set hint(String hint) {
    _attributedHint = AttributedString(hint);
    _hasBeenAnnotated = true;
  }

  /// A brief description of the result of performing an action on this node in
  /// [AttributedString] format.
  ///
  /// On iOS this is used for the `accessibilityAttributedHint` property
  /// defined in the `UIAccessibility` Protocol. On Android it is concatenated
  /// together with [attributedLabel] and [attributedValue] in the following
  /// order: [attributedValue], [attributedLabel], [attributedHint]. The
  /// concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [hint], which is the raw text of this property.
  AttributedString get attributedHint => _attributedHint;
  AttributedString _attributedHint = AttributedString('');
  set attributedHint(AttributedString attributedHint) {
    _attributedHint = attributedHint;
    _hasBeenAnnotated = true;
  }

  /// A textual description of the widget's tooltip.
  ///
  /// The reading direction is given by [textDirection].
  String get tooltip => _tooltip;
  String _tooltip = '';
  set tooltip(String tooltip) {
    _tooltip = tooltip;
    _hasBeenAnnotated = true;
  }

  /// Provides hint values which override the default hints on supported
  /// platforms.
  SemanticsHintOverrides? get hintOverrides => _hintOverrides;
  SemanticsHintOverrides? _hintOverrides;
  set hintOverrides(SemanticsHintOverrides? value) {
    if (value == null) {
      return;
    }
    _hintOverrides = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the semantics node is the root of a subtree for which values
  /// should be announced.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.scopesRoute], for a full description of route scoping.
  bool get scopesRoute => _flags.scopesRoute;
  set scopesRoute(bool value) {
    _flags = _flags.copyWith(scopesRoute: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the semantics node contains the label of a route.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.namesRoute], for a full description of route naming.
  bool get namesRoute => _flags.namesRoute;
  set namesRoute(bool value) {
    _flags = _flags.copyWith(namesRoute: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the semantics node represents an image.
  bool get isImage => _flags.isImage;
  set isImage(bool value) {
    _flags = _flags.copyWith(isImage: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the semantics node is a live region.
  ///
  /// A live region indicates that updates to semantics node are important.
  /// Platforms may use this information to make polite announcements to the
  /// user to inform them of updates to this node.
  ///
  /// An example of a live region is a [SnackBar] widget. On Android and iOS,
  /// live region causes a polite announcement to be generated automatically,
  /// even if the widget does not have accessibility focus. This announcement
  /// may not be spoken if the OS accessibility services are already
  /// announcing something else, such as reading the label of a focused widget
  /// or providing a system announcement.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isLiveRegion], the semantics flag that this setting controls.
  bool get liveRegion => _flags.isLiveRegion;
  set liveRegion(bool value) {
    _flags = _flags.copyWith(isLiveRegion: value);
    _hasBeenAnnotated = true;
  }

  /// The reading direction for the text in [label], [value], [hint],
  /// [increasedValue], and [decreasedValue].
  TextDirection? get textDirection => _textDirection;
  TextDirection? _textDirection;
  set textDirection(TextDirection? textDirection) {
    _textDirection = textDirection;
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is selected (true) or not (false).
  ///
  /// This is different from having accessibility focus. The element that is
  /// accessibility focused may or may not be selected; e.g. a [ListTile] can have
  /// accessibility focus but have its [ListTile.selected] property set to false,
  /// in which case it will not be flagged as selected.
  bool get isSelected => _flags.isSelected == Tristate.isTrue;
  set isSelected(bool value) {
    _flags = _flags.copyWith(isSelected: _tristateFromBoolOrNull(value));
    _hasBeenAnnotated = true;
  }

  /// If this node has Boolean state that can be controlled by the user, whether
  /// that state is expanded or collapsed, corresponding to true and false, respectively.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have expanded/collapsed state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// expanded/collapsed state.
  bool? get isExpanded => _flags.isExpanded.toBoolOrNull();
  set isExpanded(bool? value) {
    _flags = _flags.copyWith(isExpanded: _tristateFromBoolOrNull(value));
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is currently enabled.
  ///
  /// A disabled object does not respond to user interactions. Only objects that
  /// usually respond to user interactions, but which currently do not (like a
  /// disabled button) should be marked as disabled.
  ///
  /// The setter should not be called for objects (like static text) that never
  /// respond to user interactions.
  ///
  /// The getter will return null if the owning [RenderObject] doesn't support
  /// the concept of being enabled/disabled.
  ///
  /// This property does not control whether semantics are enabled. If you wish to
  /// disable semantics for a particular widget, you should use an [ExcludeSemantics]
  /// widget.
  bool? get isEnabled => _flags.isEnabled.toBoolOrNull();
  set isEnabled(bool? value) {
    _flags = _flags.copyWith(isEnabled: _tristateFromBoolOrNull(value));
    _hasBeenAnnotated = true;
  }

  /// If this node has Boolean state that can be controlled by the user, whether
  /// that state is checked or unchecked, corresponding to true and false,
  /// respectively.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have checked/unchecked state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// checked/unchecked state.
  bool? get isChecked =>
      _flags.isChecked == CheckedState.none ? null : _flags.isChecked == CheckedState.isTrue;
  set isChecked(bool? value) {
    if (value != null) {
      _flags = _flags.copyWith(isChecked: value ? CheckedState.isTrue : CheckedState.isFalse);
    }
    _hasBeenAnnotated = true;
  }

  /// If this node has tristate that can be controlled by the user, whether
  /// that state is in its mixed state.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have checked/unchecked state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// mixed checked state.
  bool? get isCheckStateMixed =>
      _flags.isChecked == CheckedState.none ? null : _flags.isChecked == CheckedState.mixed;
  set isCheckStateMixed(bool? value) {
    if (value ?? false) {
      _flags = _flags.copyWith(isChecked: CheckedState.mixed);
    }
    _hasBeenAnnotated = true;
  }

  /// If this node has Boolean state that can be controlled by the user, whether
  /// that state is on or off, corresponding to true and false, respectively.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have on/off state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// on/off state.
  bool? get isToggled => _flags.isToggled.toBoolOrNull();
  set isToggled(bool? value) {
    _flags = _flags.copyWith(isToggled: _tristateFromBoolOrNull(value));
    _hasBeenAnnotated = true;
  }

  /// Whether the owning RenderObject corresponds to UI that allows the user to
  /// pick one of several mutually exclusive options.
  ///
  /// For example, a [Radio] button is in a mutually exclusive group because
  /// only one radio button in that group can be marked as [isChecked].
  bool get isInMutuallyExclusiveGroup => _flags.isInMutuallyExclusiveGroup;
  set isInMutuallyExclusiveGroup(bool value) {
    _flags = _flags.copyWith(isInMutuallyExclusiveGroup: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] can hold the input focus.
  @Deprecated(
    'Check if isFocused is null instead. '
    'This feature was deprecated after v3.36.0-0.0.pre.',
  )
  bool get isFocusable => _flags.isFocused != Tristate.none;

  @Deprecated(
    'Setting isFocused automatically set this to true. '
    'This feature was deprecated after v3.36.0-0.0.pre.',
  )
  set isFocusable(bool value) {
    // If value is false, set `isFocused` to none.
    // If value is true, `isFocused` should be true or false. If `isFocused` is not none,
    // don't change it, if `isFocused` is `none`, change it to `false`.
    if (!value) {
      _flags = _flags.copyWith(isFocused: Tristate.none);
    } else {
      if (_flags.isFocused == Tristate.none) {
        _flags = _flags.copyWith(isFocused: Tristate.isFalse);
      }
    }
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] currently holds the input focus.
  bool? get isFocused => _flags.isFocused.toBoolOrNull();
  set isFocused(bool? value) {
    _flags = _flags.copyWith(isFocused: _tristateFromBoolOrNull(value));
    _hasBeenAnnotated = true;
  }

  AccessibilityFocusBlockType _accessibilityFocusBlockType = AccessibilityFocusBlockType.none;

  /// Whether the owning [RenderObject] and its subtree
  /// is blocked in the a11y focus (different from input focus).
  AccessibilityFocusBlockType get accessibilityFocusBlockType => _accessibilityFocusBlockType;
  set accessibilityFocusBlockType(AccessibilityFocusBlockType value) {
    _accessibilityFocusBlockType = value;
    _flags = _flags.copyWith(
      isAccessibilityFocusBlocked: value != AccessibilityFocusBlockType.none,
    );
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is a button (true) or not (false).
  bool get isButton => _flags.isButton;
  set isButton(bool value) {
    _flags = _flags.copyWith(isButton: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is a link (true) or not (false).
  bool get isLink => _flags.isLink;
  set isLink(bool value) {
    _flags = _flags.copyWith(isLink: value);
    _hasBeenAnnotated = true;
  }

  /// The URL that the owning [RenderObject] links to.
  Uri? get linkUrl => _linkUrl;
  Uri? _linkUrl;

  set linkUrl(Uri? value) {
    if (value == _linkUrl) {
      return;
    }
    _linkUrl = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is a header (true) or not (false).
  bool get isHeader => _flags.isHeader;
  set isHeader(bool value) {
    _flags = _flags.copyWith(isHeader: value);
    _hasBeenAnnotated = true;
  }

  /// Indicates the heading level in the document structure.
  ///
  /// This is only used for web semantics, and is ignored on other platforms.
  int get headingLevel => _headingLevel;
  int _headingLevel = 0;

  set headingLevel(int value) {
    assert(value >= 0 && value <= 6);
    if (value == headingLevel) {
      return;
    }
    _headingLevel = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is a slider (true) or not (false).
  bool get isSlider => _flags.isSlider;
  set isSlider(bool value) {
    _flags = _flags.copyWith(isSlider: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is a keyboard key (true) or not
  /// (false).
  bool get isKeyboardKey => _flags.isKeyboardKey;
  set isKeyboardKey(bool value) {
    _flags = _flags.copyWith(isKeyboardKey: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is considered hidden.
  ///
  /// Hidden elements are currently not visible on screen. They may be covered
  /// by other elements or positioned outside of the visible area of a viewport.
  ///
  /// Hidden elements cannot gain accessibility focus though regular touch. The
  /// only way they can be focused is by moving the focus to them via linear
  /// navigation.
  ///
  /// Platforms are free to completely ignore hidden elements and new platforms
  /// are encouraged to do so.
  ///
  /// Instead of marking an element as hidden it should usually be excluded from
  /// the semantics tree altogether. Hidden elements are only included in the
  /// semantics tree to work around platform limitations and they are mainly
  /// used to implement accessibility scrolling on iOS.
  bool get isHidden => _flags.isHidden;
  set isHidden(bool value) {
    _flags = _flags.copyWith(isHidden: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is a text field.
  bool get isTextField => _flags.isTextField;
  set isTextField(bool value) {
    _flags = _flags.copyWith(isTextField: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is read only.
  ///
  /// Only applicable when [isTextField] is true.
  bool get isReadOnly => _flags.isReadOnly;
  set isReadOnly(bool value) {
    _flags = _flags.copyWith(isReadOnly: value);
    _hasBeenAnnotated = true;
  }

  /// Whether [value] should be obscured.
  ///
  /// This option is usually set in combination with [isTextField] to indicate
  /// that the text field contains a password (or other sensitive information).
  /// Doing so instructs screen readers to not read out [value].
  bool get isObscured => _flags.isObscured;
  set isObscured(bool value) {
    _flags = _flags.copyWith(isObscured: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the text field is multiline.
  ///
  /// This option is usually set in combination with [isTextField] to indicate
  /// that the text field is configured to be multiline.
  bool get isMultiline => _flags.isMultiline;
  set isMultiline(bool value) {
    _flags = _flags.copyWith(isMultiline: value);
    _hasBeenAnnotated = true;
  }

  /// Whether the semantics node has a required state.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have a required state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have a
  /// required state.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isRequired], for a full description of required nodes.
  bool? get isRequired => _flags.isRequired.toBoolOrNull();
  set isRequired(bool? value) {
    _flags = _flags.copyWith(isRequired: _tristateFromBoolOrNull(value));
    _hasBeenAnnotated = true;
  }

  /// Whether the platform can scroll the semantics node when the user attempts
  /// to move focus to an offscreen child.
  ///
  /// For example, a [ListView] widget has implicit scrolling so that users can
  /// easily move to the next visible set of children. A [TabBar] widget does
  /// not have implicit scrolling, so that users can navigate into the tab
  /// body when reaching the end of the tab bar.
  bool get hasImplicitScrolling => _flags.hasImplicitScrolling;
  set hasImplicitScrolling(bool value) {
    _flags = _flags.copyWith(hasImplicitScrolling: value);
    _hasBeenAnnotated = true;
  }

  /// The currently selected text (or the position of the cursor) within
  /// [value] if this node represents a text field.
  TextSelection? get textSelection => _textSelection;
  TextSelection? _textSelection;
  set textSelection(TextSelection? value) {
    assert(value != null);
    _textSelection = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  double? get scrollPosition => _scrollPosition;
  double? _scrollPosition;
  set scrollPosition(double? value) {
    assert(value != null);
    _scrollPosition = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  double? get scrollExtentMax => _scrollExtentMax;
  double? _scrollExtentMax;
  set scrollExtentMax(double? value) {
    assert(value != null);
    _scrollExtentMax = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent], from where this value is usually taken.
  double? get scrollExtentMin => _scrollExtentMin;
  double? _scrollExtentMin;
  set scrollExtentMin(double? value) {
    assert(value != null);
    _scrollExtentMin = value;
    _hasBeenAnnotated = true;
  }

  /// The [SemanticsNode.identifier]s of widgets controlled by this node.
  Set<String>? get controlsNodes => _controlsNodes;
  Set<String>? _controlsNodes;
  set controlsNodes(Set<String>? value) {
    assert(value != null);
    _controlsNodes = value;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.validationResult}
  SemanticsValidationResult get validationResult => _validationResult;
  SemanticsValidationResult _validationResult = SemanticsValidationResult.none;
  set validationResult(SemanticsValidationResult value) {
    _validationResult = value;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.hitTestBehavior}
  ui.SemanticsHitTestBehavior get hitTestBehavior => _hitTestBehavior;
  ui.SemanticsHitTestBehavior _hitTestBehavior = ui.SemanticsHitTestBehavior.defer;
  set hitTestBehavior(ui.SemanticsHitTestBehavior value) {
    _hitTestBehavior = value;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.inputType}
  SemanticsInputType get inputType => _inputType;
  SemanticsInputType _inputType = SemanticsInputType.none;
  set inputType(SemanticsInputType value) {
    _inputType = value;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.maxValue}
  String? get maxValue => _maxValue;
  String? _maxValue;
  set maxValue(String? value) {
    _maxValue = value;
    _hasBeenAnnotated = true;
  }

  /// {@macro flutter.semantics.SemanticsProperties.minValue}
  String? get minValue => _minValue;
  String? _minValue;
  set minValue(String? value) {
    _minValue = value;
    _hasBeenAnnotated = true;
  }

  // TAGS

  /// The set of tags that this configuration wants to add to all child
  /// [SemanticsNode]s.
  ///
  /// See also:
  ///
  ///  * [addTagForChildren] to add a tag and for more information about their
  ///    usage.
  Iterable<SemanticsTag>? get tagsForChildren => _tagsForChildren;

  /// Whether this configuration will tag the child semantics nodes with a
  /// given [SemanticsTag].
  bool tagsChildrenWith(SemanticsTag tag) => _tagsForChildren?.contains(tag) ?? false;

  Set<SemanticsTag>? _tagsForChildren;

  /// Specifies a [SemanticsTag] that this configuration wants to apply to all
  /// child [SemanticsNode]s.
  ///
  /// The tag is added to all [SemanticsNode] that pass through the
  /// [RenderObject] owning this configuration while looking to be attached to a
  /// parent [SemanticsNode].
  ///
  /// Tags are used to communicate to a parent [SemanticsNode] that a child
  /// [SemanticsNode] was passed through a particular [RenderObject]. The parent
  /// can use this information to determine the shape of the semantics tree.
  ///
  /// See also:
  ///
  ///  * [RenderViewport.excludeFromScrolling] for an example of
  ///    how tags are used.
  void addTagForChildren(SemanticsTag tag) {
    _tagsForChildren ??= <SemanticsTag>{};
    _tagsForChildren!.add(tag);
  }

  // INTERNAL FLAG MANAGEMENT

  SemanticsFlags _flags = SemanticsFlags.none;

  bool get _hasExplicitRole {
    if (_role != SemanticsRole.none) {
      return true;
    }
    if (_flags.isTextField ||
        // In non web platforms, the header is a trait.
        (_flags.isHeader && kIsWeb) ||
        _flags.isSlider ||
        _flags.isLink ||
        _flags.scopesRoute ||
        _flags.isImage ||
        _flags.isKeyboardKey) {
      return true;
    }
    return false;
  }

  // CONFIGURATION COMBINATION LOGIC

  /// Whether this configuration is compatible with the provided `other`
  /// configuration.
  ///
  /// Two configurations are said to be compatible if they can be added to the
  /// same [SemanticsNode] without losing any semantics information.
  bool isCompatibleWith(SemanticsConfiguration? other) {
    if (other == null || !other.hasBeenAnnotated) {
      return true;
    }
    // The parent node should reject child node as long as their
    // traversalChildIdentifiers are different, even if the parent node has not
    // been annotated.
    if (_traversalChildIdentifier != other._traversalChildIdentifier) {
      return false;
    }
    if (!hasBeenAnnotated) {
      return true;
    }
    if (_actionsAsBits & other._actionsAsBits != 0) {
      return false;
    }
    if (_flags.hasConflictingFlags(other._flags)) {
      return false;
    }

    if (_platformViewId != null && other._platformViewId != null) {
      return false;
    }
    if (_maxValueLength != null && other._maxValueLength != null) {
      return false;
    }
    if (_currentValueLength != null && other._currentValueLength != null) {
      return false;
    }
    if (_attributedValue.string.isNotEmpty && other._attributedValue.string.isNotEmpty) {
      return false;
    }
    if (_localeForSubtree != other._localeForSubtree) {
      return false;
    }
    if (_hasExplicitRole && other._hasExplicitRole) {
      return false;
    }
    if (_hitTestBehavior != ui.SemanticsHitTestBehavior.defer ||
        other._hitTestBehavior != ui.SemanticsHitTestBehavior.defer) {
      return false;
    }
    if (_minValue != null && other._minValue != null) {
      return false;
    }
    if (_maxValue != null && other._maxValue != null) {
      return false;
    }
    return true;
  }

  /// Absorb the semantic information from `child` into this configuration.
  ///
  /// This adds the semantic information of both configurations and saves the
  /// result in this configuration.
  ///
  /// The [RenderObject] owning the `child` configuration must be a descendant
  /// of the [RenderObject] that owns this configuration.
  ///
  /// Only configurations that have [explicitChildNodes] set to false can
  /// absorb other configurations and it is recommended to only absorb compatible
  /// configurations as determined by [isCompatibleWith].
  void absorb(SemanticsConfiguration child) {
    assert(!explicitChildNodes);

    if (!child.hasBeenAnnotated) {
      return;
    }
    if (child.isBlockingUserActions) {
      child._actions.forEach((SemanticsAction key, SemanticsActionHandler value) {
        if (_kUnblockedUserActions & key.index > 0) {
          _actions[key] = value;
        }
      });
    } else {
      _actions.addAll(child._actions);
    }
    _actionsAsBits |= child._effectiveActionsAsBits;
    _customSemanticsActions.addAll(child._customSemanticsActions);
    _flags = _flags.merge(child._flags);
    _linkUrl ??= child._linkUrl;
    _textSelection ??= child._textSelection;
    _scrollPosition ??= child._scrollPosition;
    _scrollExtentMax ??= child._scrollExtentMax;
    _scrollExtentMin ??= child._scrollExtentMin;
    _hintOverrides ??= child._hintOverrides;
    _indexInParent ??= child.indexInParent;
    _scrollIndex ??= child._scrollIndex;
    _scrollChildCount ??= child._scrollChildCount;
    _platformViewId ??= child._platformViewId;
    _maxValueLength ??= child._maxValueLength;
    _currentValueLength ??= child._currentValueLength;
    // A node cannot have both `_traversalChildIdentifier` and
    // `_traversalParentIdentifier` not null.
    if (_traversalChildIdentifier == null) {
      _traversalParentIdentifier ??= child._traversalParentIdentifier;
    }
    _traversalChildIdentifier ??= child._traversalChildIdentifier;

    _headingLevel = _mergeHeadingLevels(
      sourceLevel: child._headingLevel,
      targetLevel: _headingLevel,
    );

    textDirection ??= child.textDirection;
    _sortKey ??= child._sortKey;
    if (_identifier == '') {
      _identifier = child._identifier;
    }
    _attributedLabel = _concatAttributedString(
      thisAttributedString: _attributedLabel,
      thisTextDirection: textDirection,
      otherAttributedString: child._attributedLabel,
      otherTextDirection: child.textDirection,
    );
    if (_attributedValue.string == '') {
      _attributedValue = child._attributedValue;
    }
    if (_attributedIncreasedValue.string == '') {
      _attributedIncreasedValue = child._attributedIncreasedValue;
    }
    if (_attributedDecreasedValue.string == '') {
      _attributedDecreasedValue = child._attributedDecreasedValue;
    }
    if (_role == SemanticsRole.none) {
      _role = child._role;
    }
    if (_inputType == SemanticsInputType.none) {
      _inputType = child._inputType;
    }
    _attributedHint = _concatAttributedString(
      thisAttributedString: _attributedHint,
      thisTextDirection: textDirection,
      otherAttributedString: child._attributedHint,
      otherTextDirection: child.textDirection,
    );
    if (_tooltip == '') {
      _tooltip = child._tooltip;
    }

    if (_controlsNodes == null) {
      _controlsNodes = child._controlsNodes;
    } else if (child._controlsNodes != null) {
      _controlsNodes = <String>{..._controlsNodes!, ...child._controlsNodes!};
    }

    if (child._validationResult != _validationResult) {
      if (child._validationResult == SemanticsValidationResult.invalid) {
        // Invalid result always takes precedence.
        _validationResult = SemanticsValidationResult.invalid;
      } else if (_validationResult == SemanticsValidationResult.none) {
        _validationResult = child._validationResult;
      }
    }
    _accessibilityFocusBlockType = _accessibilityFocusBlockType._merge(
      child._accessibilityFocusBlockType,
    );
    _minValue ??= child._minValue;
    _maxValue ??= child._maxValue;

    if (_hitTestBehavior == ui.SemanticsHitTestBehavior.defer &&
        child._hitTestBehavior != ui.SemanticsHitTestBehavior.defer) {
      _hitTestBehavior = child._hitTestBehavior;
    }

    _hasBeenAnnotated = hasBeenAnnotated || child.hasBeenAnnotated;
  }

  /// Returns an exact copy of this configuration.
  SemanticsConfiguration copy() {
    return SemanticsConfiguration()
      .._isSemanticBoundary = _isSemanticBoundary
      ..explicitChildNodes = explicitChildNodes
      ..isBlockingSemanticsOfPreviouslyPaintedNodes = isBlockingSemanticsOfPreviouslyPaintedNodes
      .._hasBeenAnnotated = hasBeenAnnotated
      .._isMergingSemanticsOfDescendants = _isMergingSemanticsOfDescendants
      .._textDirection = _textDirection
      .._sortKey = _sortKey
      .._identifier = _identifier
      .._traversalParentIdentifier = _traversalParentIdentifier
      .._traversalChildIdentifier = _traversalChildIdentifier
      .._attributedLabel = _attributedLabel
      .._attributedIncreasedValue = _attributedIncreasedValue
      .._attributedValue = _attributedValue
      .._attributedDecreasedValue = _attributedDecreasedValue
      .._attributedHint = _attributedHint
      .._accessibilityFocusBlockType = _accessibilityFocusBlockType
      .._hintOverrides = _hintOverrides
      .._tooltip = _tooltip
      .._flags = _flags
      .._tagsForChildren = _tagsForChildren
      .._textSelection = _textSelection
      .._scrollPosition = _scrollPosition
      .._scrollExtentMax = _scrollExtentMax
      .._scrollExtentMin = _scrollExtentMin
      .._actionsAsBits = _actionsAsBits
      .._indexInParent = indexInParent
      .._scrollIndex = _scrollIndex
      .._scrollChildCount = _scrollChildCount
      .._platformViewId = _platformViewId
      .._maxValueLength = _maxValueLength
      .._currentValueLength = _currentValueLength
      .._actions.addAll(_actions)
      .._customSemanticsActions.addAll(_customSemanticsActions)
      ..isBlockingUserActions = isBlockingUserActions
      .._headingLevel = _headingLevel
      .._linkUrl = _linkUrl
      .._role = _role
      .._controlsNodes = _controlsNodes
      .._validationResult = _validationResult
      .._inputType = _inputType
      .._hitTestBehavior = _hitTestBehavior
      .._traversalChildIdentifier = _traversalChildIdentifier
      .._traversalParentIdentifier = _traversalParentIdentifier
      .._minValue = _minValue
      .._maxValue = _maxValue;
  }
}

/// Used by [debugDumpSemanticsTree] to specify the order in which child nodes
/// are printed.
enum DebugSemanticsDumpOrder {
  /// Print nodes in inverse hit test order.
  ///
  /// In inverse hit test order, the last child of a [SemanticsNode] will be
  /// asked first if it wants to respond to a user's interaction, followed by
  /// the second last, etc. until a taker is found.
  inverseHitTest,

  /// Print nodes in semantic traversal order.
  ///
  /// This is the order in which a user would navigate the UI using the "next"
  /// and "previous" gestures.
  traversalOrder,
}

AttributedString _concatAttributedString({
  required AttributedString thisAttributedString,
  required AttributedString otherAttributedString,
  required TextDirection? thisTextDirection,
  required TextDirection? otherTextDirection,
}) {
  if (otherAttributedString.string.isEmpty) {
    return thisAttributedString;
  }
  if (thisTextDirection != otherTextDirection && otherTextDirection != null) {
    final AttributedString directionEmbedding = switch (otherTextDirection) {
      TextDirection.rtl => AttributedString(Unicode.RLE),
      TextDirection.ltr => AttributedString(Unicode.LRE),
    };
    otherAttributedString =
        directionEmbedding + otherAttributedString + AttributedString(Unicode.PDF);
  }
  if (thisAttributedString.string.isEmpty) {
    return otherAttributedString;
  }

  return thisAttributedString + AttributedString('\n') + otherAttributedString;
}

/// Base class for all sort keys for [SemanticsProperties.sortKey] accessibility
/// traversal order sorting.
///
/// Sort keys are sorted by [name], then by the comparison that the subclass
/// implements. If [SemanticsProperties.sortKey] is specified, sort keys within
/// the same semantic group must all be of the same type.
///
/// Keys with no [name] are compared to other keys with no [name], and will
/// be traversed before those with a [name].
///
/// If no sort key is applied to a semantics node, then it will be ordered using
/// a platform dependent default algorithm.
///
/// See also:
///
///  * [OrdinalSortKey] for a sort key that sorts using an ordinal.
abstract class SemanticsSortKey with Diagnosticable implements Comparable<SemanticsSortKey> {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const SemanticsSortKey({this.name});

  /// An optional name that will group this sort key with other sort keys of the
  /// same [name].
  ///
  /// Sort keys must have the same `runtimeType` when compared.
  ///
  /// Keys with no [name] are compared to other keys with no [name], and will
  /// be traversed before those with a [name].
  final String? name;

  @override
  int compareTo(SemanticsSortKey other) {
    // Sort by name first and then subclass ordering.
    assert(
      runtimeType == other.runtimeType,
      'Semantics sort keys can only be compared to other sort keys of the same type.',
    );

    // Defer to the subclass implementation for ordering only if the names are
    // identical (or both null).
    if (name == other.name) {
      return doCompare(other);
    }

    // Keys that don't have a name are sorted together and come before those with
    // a name.
    if (name == null && other.name != null) {
      return -1;
    } else if (name != null && other.name == null) {
      return 1;
    }

    return name!.compareTo(other.name!);
  }

  /// The implementation of [compareTo].
  ///
  /// The argument is guaranteed to be of the same type as this object and have
  /// the same [name].
  ///
  /// The method should return a negative number if this object comes earlier in
  /// the sort order than the argument; and a positive number if it comes later
  /// in the sort order. Returning zero causes the system to use default sort
  /// order.
  @protected
  int doCompare(covariant SemanticsSortKey other);

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('name', name, defaultValue: null));
  }
}

/// A [SemanticsSortKey] that sorts based on the `double` value it is
/// given.
///
/// The [OrdinalSortKey] compares itself with other [OrdinalSortKey]s
/// to sort based on the order it is given.
///
/// [OrdinalSortKey]s are sorted by the optional [name], then by their [order].
/// If [SemanticsProperties.sortKey] is a [OrdinalSortKey], then all the other
/// specified sort keys in the same semantics group must also be
/// [OrdinalSortKey]s.
///
/// Keys with no [name] are compared to other keys with no [name], and will
/// be traversed before those with a [name].
///
/// The ordinal value [order] is typically a whole number, though it can be
/// fractional, e.g. in order to fit between two other consecutive whole
/// numbers. The value must be finite (it cannot be [double.nan],
/// [double.infinity], or [double.negativeInfinity]).
class OrdinalSortKey extends SemanticsSortKey {
  /// Creates a const semantics sort key that uses a [double] as its key value.
  ///
  /// The [order] must be a finite number.
  const OrdinalSortKey(this.order, {super.name})
    : assert(order > double.negativeInfinity),
      assert(order < double.infinity);

  /// Determines the placement of this key in a sequence of keys that defines
  /// the order in which this node is traversed by the platform's accessibility
  /// services.
  ///
  /// Lower values will be traversed first. Keys with the same [name] will be
  /// grouped together and sorted by name first, and then sorted by [order].
  final double order;

  @override
  int doCompare(OrdinalSortKey other) {
    if (other.order == order) {
      return 0;
    }
    return order.compareTo(other.order);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DoubleProperty('order', order, defaultValue: null));
  }
}

/// Picks the most accurate heading level when two nodes, with potentially
/// different heading levels, are merged.
///
/// Argument [sourceLevel] is the heading level of the source node that is being
/// merged into a target node, which has heading level [targetLevel].
///
/// If the target node is not a heading, the the source heading level is used.
/// Otherwise, the target heading level is used irrespective of the source
/// heading level.
int _mergeHeadingLevels({required int sourceLevel, required int targetLevel}) {
  return targetLevel == 0 ? sourceLevel : targetLevel;
}

Tristate _tristateFromBoolOrNull(bool? value) {
  if (value == null) {
    return Tristate.none;
  }

  if (value) {
    return Tristate.isTrue;
  }
  return Tristate.isFalse;
}

/// This is just to support flag 0-30, new flags don't need to be in the bitmask.
int _toBitMask(SemanticsFlags flags) {
  var bitmask = 0;
  if (flags.isChecked != CheckedState.none) {
    bitmask |= 1 << 0;
  }
  if (flags.isChecked == CheckedState.isTrue) {
    bitmask |= 1 << 1;
  }
  if (flags.isSelected == Tristate.isTrue) {
    bitmask |= 1 << 2;
  }
  if (flags.isButton) {
    bitmask |= 1 << 3;
  }
  if (flags.isTextField) {
    bitmask |= 1 << 4;
  }
  if (flags.isFocused == Tristate.isTrue) {
    bitmask |= 1 << 5;
  }
  if (flags.isEnabled != Tristate.none) {
    bitmask |= 1 << 6;
  }
  if (flags.isEnabled == Tristate.isTrue) {
    bitmask |= 1 << 7;
  }
  if (flags.isInMutuallyExclusiveGroup) {
    bitmask |= 1 << 8;
  }
  if (flags.isHeader) {
    bitmask |= 1 << 9;
  }
  if (flags.isObscured) {
    bitmask |= 1 << 10;
  }
  if (flags.scopesRoute) {
    bitmask |= 1 << 11;
  }
  if (flags.namesRoute) {
    bitmask |= 1 << 12;
  }
  if (flags.isHidden) {
    bitmask |= 1 << 13;
  }
  if (flags.isImage) {
    bitmask |= 1 << 14;
  }
  if (flags.isLiveRegion) {
    bitmask |= 1 << 15;
  }
  if (flags.isToggled != Tristate.none) {
    bitmask |= 1 << 16;
  }
  if (flags.isToggled == Tristate.isTrue) {
    bitmask |= 1 << 17;
  }
  if (flags.hasImplicitScrolling) {
    bitmask |= 1 << 18;
  }
  if (flags.isMultiline) {
    bitmask |= 1 << 19;
  }
  if (flags.isReadOnly) {
    bitmask |= 1 << 20;
  }
  if (flags.isFocused != Tristate.none) {
    bitmask |= 1 << 21;
  }
  if (flags.isLink) {
    bitmask |= 1 << 22;
  }
  if (flags.isSlider) {
    bitmask |= 1 << 23;
  }
  if (flags.isKeyboardKey) {
    bitmask |= 1 << 24;
  }
  if (flags.isChecked == CheckedState.mixed) {
    bitmask |= 1 << 25;
  }
  if (flags.isExpanded != Tristate.none) {
    bitmask |= 1 << 26;
  }
  if (flags.isExpanded == Tristate.isTrue) {
    bitmask |= 1 << 27;
  }
  if (flags.isSelected != Tristate.none) {
    bitmask |= 1 << 28;
  }
  if (flags.isRequired != Tristate.none) {
    bitmask |= 1 << 29;
  }
  if (flags.isRequired == Tristate.isTrue) {
    bitmask |= 1 << 30;
  }
  return bitmask;
}
