<commit_before>/* Copyright (c) 2014-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#import "_ASDisplayViewAccessiblity.h"
#import "_ASDisplayView.h"
#import "ASDisplayNodeExtras.h"
#import "ASDisplayNode+FrameworkPrivate.h"

#import <objc/runtime.h>


#pragma mark - UIAccessibilityElement

@implementation UIAccessibilityElement (_ASDisplayView)

+ (UIAccessibilityElement *)accessibilityElementWithContainer:(id)container node:(ASDisplayNode *)node
{
  UIAccessibilityElement *accessibilityElement = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:container];
  accessibilityElement.asyncdisplaykit_node = node;
  return accessibilityElement;
}

- (void)setAsyncdisplaykit_node:(ASDisplayNode *)node
{
  objc_setAssociatedObject(self, @selector(asyncdisplaykit_node), node, OBJC_ASSOCIATION_ASSIGN);

  self.accessibilityIdentifier = node.accessibilityIdentifier;
  self.accessibilityLabel = node.accessibilityLabel;
  self.accessibilityHint = node.accessibilityHint;
  self.accessibilityValue = node.accessibilityValue;
  self.accessibilityTraits = node.accessibilityTraits;
}

- (ASDisplayNode *)asyncdisplaykit_node
{
  return objc_getAssociatedObject(self, @selector(asyncdisplaykit_node));
}

@end


#pragma mark - _ASDisplayView / UIAccessibilityContainer

static BOOL ASNodeIsAccessiblityContainer(ASDisplayNode *node) {
  return (!node.isAccessibilityElement && [node accessibilityElementCount] > 0);
}

@interface _ASDisplayView () {
  NSMutableArray *_accessibleElements;
}

@end

@implementation _ASDisplayView (UIAccessibilityContainer)

#pragma mark - UIAccessibility

- (NSArray *)accessibleElements
{
  ASDisplayNode *selfNode = self.asyncdisplaykit_node;
  if (selfNode == nil) {
    return nil;
  }
  
  _accessibleElements = [[NSMutableArray alloc] init];
  
  // Handle rasterize case
  if (selfNode.shouldRasterizeDescendants) {
    // In this case we have to go through the whole subnodes tree in BFS fashion and create all
    // accessibility elements ourselves as the view hierarchy is flattened
    ASDisplayNodePerformBlockOnEveryNodeBFS(selfNode, ^(ASDisplayNode * _Nonnull node) {
      // For every subnode we have to create a UIAccessibilityElement as we cannot just add the view to the
      // accessibleElements as for a subnode of a node with shouldRasterizeDescendants enabled no view exists
      if (node != selfNode && node.isAccessibilityElement) {
        [_accessibleElements addObject:[UIAccessibilityElement accessibilityElementWithContainer:self node:node]];
      }
    });
    return _accessibleElements;
  }
  
  // Handle not rasterize case
  // Create UI accessiblity elements for each subnode that represent an elment within the accessibility container
  for (ASDisplayNode *subnode in selfNode.subnodes) {
    if (subnode.isAccessibilityElement) {
      if (subnode.isLayerBacked) {
        // The same comment for layer backed subnodes is true as for subnodes within a shouldRasterizeDescendants node.
        // See details above
        [_accessibleElements addObject:[UIAccessibilityElement accessibilityElementWithContainer:self node:subnode]];
      } else {
        [_accessibleElements addObject:subnode.view];
      }
    } else if (ASNodeIsAccessiblityContainer(subnode)) {
      [_accessibleElements addObject:subnode.view];
    }
  }
  
  return _accessibleElements;
}

- (NSInteger)accessibilityElementCount
{
  return [self accessibleElements].count;
}

- (id)accessibilityElementAtIndex:(NSInteger)index
{
  ASDisplayNodeAssertNotNil(_accessibleElements, @"At this point _accessibleElements should be created.");
  if (_accessibleElements == nil) {
    return nil;
  }
  
  UIAccessibilityElement *accessibilityElement = [_accessibleElements objectAtIndex:index];
  ASDisplayNode *accessibilityElementNode = accessibilityElement.asyncdisplaykit_node;
  if (accessibilityElementNode == nil) {
    return nil;
  }
  
  // We have to update the accessiblity frame in accessibilityElementAtIndex: as the accessibility frame is in screen
  // coordinates and between creating the accessibilityElement and returning it in accessibilityElementAtIndex:
  // the frame can change
  
  // Handle if node is rasterized
  ASDisplayNode *selfNode = self.asyncdisplaykit_node;
  if (selfNode.shouldRasterizeDescendants) {
    // We need to convert the accessibilityElementNode frame into the coordinate system of the selfNode
    CGRect frame = [selfNode convertRect:accessibilityElementNode.bounds fromNode:accessibilityElementNode];
    accessibilityElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(frame, self);
    return accessibilityElement;
  }

  // Handle non rasterized case
  accessibilityElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(accessibilityElementNode.frame, self);
  return accessibilityElement;<commit_msg>Move setting of accessibilityFrame into accessibleElements<commit_after>/* Copyright (c) 2014-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#import "_ASDisplayViewAccessiblity.h"
#import "_ASDisplayView.h"
#import "ASDisplayNodeExtras.h"
#import "ASDisplayNode+FrameworkPrivate.h"

#import <objc/runtime.h>


#pragma mark - UIAccessibilityElement

@implementation UIAccessibilityElement (_ASDisplayView)

+ (UIAccessibilityElement *)accessibilityElementWithContainer:(id)container node:(ASDisplayNode *)node
{
  UIAccessibilityElement *accessibilityElement = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:container];
  accessibilityElement.accessibilityIdentifier = node.accessibilityIdentifier;
  accessibilityElement.accessibilityLabel = node.accessibilityLabel;
  accessibilityElement.accessibilityHint = node.accessibilityHint;
  accessibilityElement.accessibilityValue = node.accessibilityValue;
  accessibilityElement.accessibilityTraits = node.accessibilityTraits;
  return accessibilityElement;
}

@end


#pragma mark - _ASDisplayView / UIAccessibilityContainer

@interface _ASDisplayView () {
  NSMutableArray *_accessibleElements;
}

@end

@implementation _ASDisplayView (UIAccessibilityContainer)

#pragma mark - UIAccessibility

- (NSArray *)accessibleElements
{
  ASDisplayNode *selfNode = self.asyncdisplaykit_node;
  if (selfNode == nil) {
    return nil;
  }
  
  _accessibleElements = [[NSMutableArray alloc] init];
  
  // Handle rasterize case
  if (selfNode.shouldRasterizeDescendants) {
    // If the node has shouldRasterizeDescendants enabled it's necessaty to go through the whole subnodes
    // tree of the node in BFS fashion and create for all subnodes UIAccessibilityElement objects ourselves
    // as the view hierarchy is flattened
    ASDisplayNodePerformBlockOnEveryNodeBFS(selfNode, ^(ASDisplayNode * _Nonnull node) {
      // For every subnode we have to create a UIAccessibilityElement as we cannot just add the view to the
      // accessibleElements as for a subnode of a node with shouldRasterizeDescendants enabled no view exists
      if (node != selfNode && node.isAccessibilityElement) {
        UIAccessibilityElement *accessibilityElement = [UIAccessibilityElement accessibilityElementWithContainer:self node:node];
        // As the node hierarchy is flattened it's necessary to convert the frame for each subnode in the tree to the
        // coordinate system of the node with shouldRasterizeDescendants enabled
        CGRect frame = [selfNode convertRect:node.bounds fromNode:node];
        accessibilityElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(frame, self);
        [_accessibleElements addObject:accessibilityElement];
      }
    });
    return _accessibleElements;
  }
  
  // Handle not rasterize case
  // Create UI accessiblity elements for each subnode that represent an elment within the accessibility container
  for (ASDisplayNode *subnode in selfNode.subnodes) {
    if (subnode.isAccessibilityElement) {
      id accessiblityElement = nil;
      if (subnode.isLayerBacked) {
        // The same comment for layer backed nodes is true as for subnodes within a shouldRasterizeDescendants node.
        // See details above
        accessiblityElement = [UIAccessibilityElement accessibilityElementWithContainer:self node:subnode];
      } else {
        accessiblityElement = subnode.view;
      }
      [accessiblityElement setAccessibilityFrame:UIAccessibilityConvertFrameToScreenCoordinates(subnode.frame, self)];
      [_accessibleElements addObject:accessiblityElement];
    } else if ([subnode accessibilityElementCount] > 0) { // Check if it's an UIAccessibilityContainer
      [_accessibleElements addObject:subnode.view];
    }
  }
  
  return _accessibleElements;
}

- (NSInteger)accessibilityElementCount
{
  return [self accessibleElements].count;
}

- (id)accessibilityElementAtIndex:(NSInteger)index
{
  ASDisplayNodeAssertNotNil(_accessibleElements, @"At this point _accessibleElements should be created.");
  if (_accessibleElements == nil) {
    return nil;
  }
  
  return _accessibleElements[index];
{'fraction_non_alphanumeric': 0.0703942500792728, 'fraction_numerical': 0.0010569707219110032, 'mean_word_length': 4.906367041198502, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1884159', 'n_tokens_mistral': 2588, 'n_tokens_neox': 2514, 'n_words': 722}