Skip to content

Commit

Permalink
C++ Cleanup 1/N: Reorganize YGStyle (facebook#1349)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#1349

X-link: facebook/react-native#39171

## This diff

This diff adds a `style` directory for code related to storing and manipulating styles. `YGStyle`, which is not a public API, is renamed to `yoga::Style` and moved into this folder, alongside `CompactValue`. We will eventually add `ValuePool` alongside this for the next generation style representation.

## This stack

The organization of the C++ internals of Yoga are in need of attention.
1. Some of the C++ internals are namespaced, but others not.
2. Some of the namespaces include `detail`, but are meant to be used outside of the translation unit (FB Clang Tidy rules warn on any usage of these)
2. Most of the files are in a flat hierarchy, except for event tracing in its own folder
3. Some files and functions begin with YG, others don’t
4. Some functions are uppercase, others are not
5. Almost all of the interesting logic is in Yoga.cpp, and the file is too large to reason about
6. There are multiple grab bag files where folks put random functions they need in (Utils, BitUtils, Yoga-Internal.h)
7. There is no clear indication from file structure or type naming what is private vs not
8. Handles like `YGNodeRef` and `YGConfigRef` can be used to access internals just by importing headers

This stack does some much needed spring cleaning:
1. All non-public headers and C++ implementation details are in separate folders from the root level `yoga`. This will give us room to split up logic and add more files without too large a flat hierarchy
3. All private C++ internals are under the `facebook::yoga` namespace. Details namespaces are only ever used within the same header, as they are intended
4. Utils files are split
5. Most C++ internals drop the YG prefix
6. Most C++ internal function names are all lower camel case
7. We start to split up Yoga.cpp
8. Every header beginning with YG or at the top-level directory is public and C only, with the exception of Yoga-Internal.h which has non-public functions for bindings
9. It is not possible to use private APIs without static casting handles to internal classes

This will give us more leeway to continue splitting monolithic files, and consistent guidelines for style in new files as well.

These changes should not be breaking to any project using only public Yoga headers. This includes every usage of Yoga in fbsource except for RN Fabric which is currently tied to internals. This refactor should make that boundary clearer.

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D48710084

fbshipit-source-id: b7da0b4b8b3b89870b79eef875244ee2f2a8c47f
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Aug 30, 2023
1 parent 49fbd40 commit ea2051a
Show file tree
Hide file tree
Showing 15 changed files with 182 additions and 183 deletions.
11 changes: 9 additions & 2 deletions Yoga.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ Pod::Spec.new do |spec|
'-std=c++17',
'-fPIC'
]
spec.source_files = 'yoga/**/*.{h,cpp}'
spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h'

spec.swift_version = '5.1'
spec.source_files = 'yoga/**/*.{h,cpp}'
spec.header_mappings_dir = 'yoga'

public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h'
spec.public_header_files = public_header_files

all_header_files = 'yoga/**/*.h'
spec.private_header_files = Dir.glob(all_header_files) - Dir.glob(public_header_files)
end
4 changes: 2 additions & 2 deletions tests/CompactValueTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

#define YOGA_COMPACT_VALUE_TEST

#include <yoga/CompactValue.h>
#include <yoga/style/CompactValue.h>
#include <gtest/gtest.h>
#include <cmath>

using facebook::yoga::detail::CompactValue;
using facebook::yoga::CompactValue;

const auto tooSmall = nextafterf(CompactValue::LOWER_BOUND, -INFINITY);
const auto tooLargePoints =
Expand Down
31 changes: 14 additions & 17 deletions tests/YGStyleAccessorsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
#include <cstdint>
#include <type_traits>
#include <gtest/gtest.h>
#include <yoga/YGEnums.h>
#include <yoga/YGStyle.h>
#include <yoga/YGValue.h>
#include <yoga/Yoga.h>
#include <yoga/style/Style.h>

#define ACCESSOR_TESTS_1(NAME, X) \
style.NAME() = X; \
Expand All @@ -31,14 +30,14 @@
#define ACCESSOR_TESTS_N(a, b, c, d, e, COUNT, ...) ACCESSOR_TESTS_##COUNT
#define ACCESSOR_TESTS(...) ACCESSOR_TESTS_N(__VA_ARGS__, 5, 4, 3, 2, 1)

#define INDEX_ACCESSOR_TESTS_1(NAME, IDX, X) \
{ \
auto style = YGStyle{}; \
style.NAME()[IDX] = X; \
ASSERT_EQ(style.NAME()[IDX], X); \
auto asArray = decltype(std::declval<const YGStyle&>().NAME()){X}; \
style.NAME() = asArray; \
ASSERT_EQ(static_cast<decltype(asArray)>(style.NAME()), asArray); \
#define INDEX_ACCESSOR_TESTS_1(NAME, IDX, X) \
{ \
auto style = Style{}; \
style.NAME()[IDX] = X; \
ASSERT_EQ(style.NAME()[IDX], X); \
auto asArray = decltype(std::declval<const Style&>().NAME()){X}; \
style.NAME() = asArray; \
ASSERT_EQ(static_cast<decltype(asArray)>(style.NAME()), asArray); \
}

#define INDEX_ACCESSOR_TESTS_2(NAME, IDX, X, Y) \
Expand All @@ -64,22 +63,20 @@

// test macro for up to 5 values. If more are needed, extend the macros above.
#define ACCESSOR_TEST(NAME, DEFAULT_VAL, ...) \
TEST(YGStyle, style_##NAME##_access) { \
auto style = YGStyle{}; \
TEST(Style, style_##NAME##_access) { \
auto style = Style{}; \
ASSERT_EQ(style.NAME(), DEFAULT_VAL); \
ACCESSOR_TESTS(__VA_ARGS__)(NAME, __VA_ARGS__) \
}

#define INDEX_ACCESSOR_TEST(NAME, DEFAULT_VAL, IDX, ...) \
TEST(YGStyle, style_##NAME##_access) { \
ASSERT_EQ(YGStyle{}.NAME()[IDX], DEFAULT_VAL); \
TEST(Style, style_##NAME##_access) { \
ASSERT_EQ(Style{}.NAME()[IDX], DEFAULT_VAL); \
INDEX_ACCESSOR_TESTS(__VA_ARGS__)(NAME, IDX, __VA_ARGS__) \
}

namespace facebook::yoga {

using CompactValue = detail::CompactValue;

// TODO: MSVC doesn't like the macros
#ifndef _MSC_VER

Expand Down
12 changes: 6 additions & 6 deletions yoga/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#pragma once

#include "YGNode.h"
#include "Yoga-internal.h"
#include "CompactValue.h"
#include <yoga/Yoga-internal.h>
#include <yoga/style/CompactValue.h>

// This struct is an helper model to hold the data for step 4 of flexbox algo,
// which is collecting the flex items in a line.
Expand Down Expand Up @@ -56,8 +56,8 @@ struct YGCollectFlexItemsRowValues {

bool YGValueEqual(const YGValue& a, const YGValue& b);
inline bool YGValueEqual(
facebook::yoga::detail::CompactValue a,
facebook::yoga::detail::CompactValue b) {
facebook::yoga::CompactValue a,
facebook::yoga::CompactValue b) {
return YGValueEqual((YGValue) a, (YGValue) b);
}

Expand Down Expand Up @@ -115,7 +115,7 @@ inline YGFloatOptional YGResolveValue(
}

inline YGFloatOptional YGResolveValue(
facebook::yoga::detail::CompactValue value,
facebook::yoga::CompactValue value,
float ownerSize) {
return YGResolveValue((YGValue) value, ownerSize);
}
Expand All @@ -140,7 +140,7 @@ inline YGFlexDirection YGResolveFlexDirection(
}

inline YGFloatOptional YGResolveValueMargin(
facebook::yoga::detail::CompactValue value,
facebook::yoga::CompactValue value,
const float ownerSize) {
return value.isAuto() ? YGFloatOptional{0} : YGResolveValue(value, ownerSize);
}
4 changes: 2 additions & 2 deletions yoga/YGConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

#include <yoga/Yoga.h>

#include "BitUtils.h"
#include "Yoga-internal.h"
#include <yoga/BitUtils.h>
#include <yoga/Yoga-internal.h>

namespace facebook::yoga {

Expand Down
2 changes: 1 addition & 1 deletion yoga/YGFloatOptional.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include <cmath>
#include <limits>
#include "Yoga-internal.h"
#include <yoga/Yoga-internal.h>

struct YGFloatOptional {
private:
Expand Down
6 changes: 3 additions & 3 deletions yoga/YGLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

#pragma once

#include "BitUtils.h"
#include "YGFloatOptional.h"
#include "Yoga-internal.h"
#include <yoga/BitUtils.h>
#include <yoga/YGFloatOptional.h>
#include <yoga/Yoga-internal.h>

struct YGLayout {
std::array<float, 4> position = {};
Expand Down
13 changes: 7 additions & 6 deletions yoga/YGNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
#include "Utils.h"

using namespace facebook;
using facebook::yoga::detail::CompactValue;
using namespace facebook::yoga;
using facebook::yoga::CompactValue;

YGNode::YGNode(const YGConfigRef config) : config_{config} {
YGAssert(
Expand Down Expand Up @@ -53,7 +54,7 @@ void YGNode::print(void* printContext) {
}

CompactValue YGNode::computeEdgeValueForRow(
const YGStyle::Edges& edges,
const Style::Edges& edges,
YGEdge rowEdge,
YGEdge edge,
CompactValue defaultValue) {
Expand All @@ -71,7 +72,7 @@ CompactValue YGNode::computeEdgeValueForRow(
}

CompactValue YGNode::computeEdgeValueForColumn(
const YGStyle::Edges& edges,
const Style::Edges& edges,
YGEdge edge,
CompactValue defaultValue) {
if (!edges[edge].isUndefined()) {
Expand All @@ -86,7 +87,7 @@ CompactValue YGNode::computeEdgeValueForColumn(
}

CompactValue YGNode::computeRowGap(
const YGStyle::Gutters& gutters,
const Style::Gutters& gutters,
CompactValue defaultValue) {
if (!gutters[YGGutterRow].isUndefined()) {
return gutters[YGGutterRow];
Expand All @@ -98,7 +99,7 @@ CompactValue YGNode::computeRowGap(
}

CompactValue YGNode::computeColumnGap(
const YGStyle::Gutters& gutters,
const Style::Gutters& gutters,
CompactValue defaultValue) {
if (!gutters[YGGutterColumn].isUndefined()) {
return gutters[YGGutterColumn];
Expand Down Expand Up @@ -431,7 +432,7 @@ YGValue YGNode::resolveFlexBasisPtr() const {

void YGNode::resolveDimension() {
using namespace yoga;
const YGStyle& style = getStyle();
const Style& style = getStyle();
for (auto dim : {YGDimensionWidth, YGDimensionHeight}) {
if (!style.maxDimensions()[dim].isUndefined() &&
YGValueEqual(style.maxDimensions()[dim], style.minDimensions()[dim])) {
Expand Down
25 changes: 13 additions & 12 deletions yoga/YGNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

#include <cstdint>
#include <stdio.h>
#include "CompactValue.h"
#include "YGConfig.h"
#include "YGLayout.h"
#include "YGStyle.h"
#include "Yoga-internal.h"
#include <yoga/Yoga-internal.h>

#include <yoga/style/CompactValue.h>
#include <yoga/style/Style.h>

YGConfigRef YGConfigGetDefault();

Expand Down Expand Up @@ -52,7 +53,7 @@ struct YOGA_EXPORT YGNode {
PrintWithContextFn withContext;
} print_ = {nullptr};
YGDirtiedFunc dirtied_ = nullptr;
YGStyle style_ = {};
facebook::yoga::Style style_ = {};
YGLayout layout_ = {};
uint32_t lineIndex_ = 0;
YGNodeRef owner_ = nullptr;
Expand Down Expand Up @@ -80,7 +81,7 @@ struct YOGA_EXPORT YGNode {
// DO NOT CHANGE THE VISIBILITY OF THIS METHOD!
YGNode& operator=(YGNode&&) = default;

using CompactValue = facebook::yoga::detail::CompactValue;
using CompactValue = facebook::yoga::CompactValue;

public:
YGNode() : YGNode{YGConfigGetDefault()} { flags_.hasNewLayout = true; }
Expand Down Expand Up @@ -123,9 +124,9 @@ struct YOGA_EXPORT YGNode {
YGDirtiedFunc getDirtied() const { return dirtied_; }

// For Performance reasons passing as reference.
YGStyle& getStyle() { return style_; }
facebook::yoga::Style& getStyle() { return style_; }

const YGStyle& getStyle() const { return style_; }
const facebook::yoga::Style& getStyle() const { return style_; }

// For Performance reasons passing as reference.
YGLayout& getLayout() { return layout_; }
Expand Down Expand Up @@ -178,22 +179,22 @@ struct YOGA_EXPORT YGNode {
}

static CompactValue computeEdgeValueForColumn(
const YGStyle::Edges& edges,
const facebook::yoga::Style::Edges& edges,
YGEdge edge,
CompactValue defaultValue);

static CompactValue computeEdgeValueForRow(
const YGStyle::Edges& edges,
const facebook::yoga::Style::Edges& edges,
YGEdge rowEdge,
YGEdge edge,
CompactValue defaultValue);

static CompactValue computeRowGap(
const YGStyle::Gutters& gutters,
const facebook::yoga::Style::Gutters& gutters,
CompactValue defaultValue);

static CompactValue computeColumnGap(
const YGStyle::Gutters& gutters,
const facebook::yoga::Style::Gutters& gutters,
CompactValue defaultValue);

// Methods related to positions, margin, padding and border
Expand Down Expand Up @@ -273,7 +274,7 @@ struct YOGA_EXPORT YGNode {

void setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { dirtied_ = dirtiedFunc; }

void setStyle(const YGStyle& style) { style_ = style; }
void setStyle(const facebook::yoga::Style& style) { style_ = style; }

void setLayout(const YGLayout& layout) { layout_ = layout; }

Expand Down
24 changes: 11 additions & 13 deletions yoga/YGNodePrint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "YGNodePrint.h"
#include "YGNode.h"
#include "Yoga-internal.h"
#include <yoga/Yoga-internal.h>
#include "Utils.h"

namespace facebook::yoga {
Expand All @@ -25,7 +25,7 @@ static void indent(string& base, uint32_t level) {
}
}

static bool areFourValuesEqual(const YGStyle::Edges& four) {
static bool areFourValuesEqual(const Style::Edges& four) {
return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) &&
YGValueEqual(four[0], four[3]);
}
Expand Down Expand Up @@ -90,10 +90,10 @@ static void appendNumberIfNotZero(
static void appendEdges(
string& base,
const string& key,
const YGStyle::Edges& edges) {
const Style::Edges& edges) {
if (areFourValuesEqual(edges)) {
auto edgeValue = YGNode::computeEdgeValueForColumn(
edges, YGEdgeLeft, detail::CompactValue::ofZero());
edges, YGEdgeLeft, CompactValue::ofZero());
appendNumberIfNotZero(base, key, edgeValue);
} else {
for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) {
Expand All @@ -106,14 +106,14 @@ static void appendEdges(
static void appendEdgeIfNotUndefined(
string& base,
const string& str,
const YGStyle::Edges& edges,
const Style::Edges& edges,
const YGEdge edge) {
// TODO: this doesn't take RTL / YGEdgeStart / YGEdgeEnd into account
auto value = (edge == YGEdgeLeft || edge == YGEdgeRight)
? YGNode::computeEdgeValueForRow(
edges, edge, edge, detail::CompactValue::ofUndefined())
edges, edge, edge, CompactValue::ofUndefined())
: YGNode::computeEdgeValueForColumn(
edges, edge, detail::CompactValue::ofUndefined());
edges, edge, CompactValue::ofUndefined());
appendNumberIfNotUndefined(base, str, value);
}

Expand Down Expand Up @@ -188,17 +188,15 @@ void YGNodeToString(
appendEdges(str, "padding", style.padding());
appendEdges(str, "border", style.border());

if (YGNode::computeColumnGap(
style.gap(), detail::CompactValue::ofUndefined()) !=
if (YGNode::computeColumnGap(style.gap(), CompactValue::ofUndefined()) !=
YGNode::computeColumnGap(
YGNode().getStyle().gap(), detail::CompactValue::ofUndefined())) {
YGNode().getStyle().gap(), CompactValue::ofUndefined())) {
appendNumberIfNotUndefined(
str, "column-gap", style.gap()[YGGutterColumn]);
}
if (YGNode::computeRowGap(
style.gap(), detail::CompactValue::ofUndefined()) !=
if (YGNode::computeRowGap(style.gap(), CompactValue::ofUndefined()) !=
YGNode::computeRowGap(
YGNode().getStyle().gap(), detail::CompactValue::ofUndefined())) {
YGNode().getStyle().gap(), CompactValue::ofUndefined())) {
appendNumberIfNotUndefined(str, "row-gap", style.gap()[YGGutterRow]);
}

Expand Down
2 changes: 1 addition & 1 deletion yoga/Yoga-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#include <yoga/Yoga.h>

#include "CompactValue.h"
#include <yoga/style/CompactValue.h>

using YGVector = std::vector<YGNodeRef>;

Expand Down
Loading

0 comments on commit ea2051a

Please sign in to comment.