This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch edje-vector-intergration
in repository efl.

View the commit online.

commit c6598f248795f46f885ed638701bb2808b945ae3
Author: [email protected] <[email protected]>
AuthorDate: Wed Apr 29 09:12:37 2026 -0600

    edje: implement description-scope override authoring (Task 4.3)
    
    Enables declarations like vector.shape { target: "body"; fill.color: ... }
    at description scope to override individual nodes from inherited base trees.
    
    Context dispatch on four sub-node openers (shape/container/gradient_linear/
    gradient_radial) checks parser state to decide between inline-tree nodes
    (existing behavior, Mode B) and description-scope override blocks (new).
    Both forms parse identically and dispatch via current_vg_tree and
    current_vg_node state.
    
    Spec deviation from Phase 2: EDC cannot parse positional quoted args between
    a keyword and brace, so override target is identified by a target: statement
    inside the block, matching Phase 2.6's stroke.dash precedent.
    
    New _vg_finalize_description_overrides handler at description-close validates:
    - Missing target: statement → VEC002 error
    - Target not found in base tree → VEC002 error
    - Type mismatch with override node type → VEC002 error
    
    Inherit handler upserts parent's _vg_desc_to_tree entry under child
    description pointer so finalizer locates the correct base tree even on
    inherited descriptions. Task 4.4 inherit-merge work builds on this.
    
    _vg_close_block replaces _vg_close_node in VG_NODE_NESTED_AT macro;
    falls back to _vg_close_node when not in override mode so toplevel
    vectors {} paths are unchanged.
    
    Test fixture: ui/box_a_hover inherits from tile_a and overrides body shape
    fill/stroke in hover state. Parses cleanly; runtime application deferred to
    Task 4.5. All 52 edje_suite tests pass.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
 src/bin/edje/edje_cc_handlers.c            | 207 +++++++++++++++++++++++++++--
 src/tests/edje/data/test_vector_states.edc |  19 +++
 2 files changed, 217 insertions(+), 9 deletions(-)

diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index 99dc50933d..cf36c20b05 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -616,6 +616,12 @@ static void       st_collections_group_parts_part_description_vector_frame(void)
 static void       st_collections_group_parts_part_description_vector_use(void);
 static void       ob_collections_group_parts_part_description_vector(void);
 static void       _vg_inline_block_end(void);
+/* Task 4.3: override block helpers */
+static void       _vg_open_override(Edje_Vg_Node_Type type);
+static void       _vg_close_block(void);
+static void       st_vg_override_target(void);
+static const char *_node_type_str(Edje_Vg_Node_Type t);
+static void       _vg_finalize_description_overrides(void);
 
 static void       ob_collections_group_programs_program(void);
 static void       st_collections_group_programs_program_name(void);
@@ -1183,6 +1189,11 @@ New_Statement_Handler statement_handlers[] =
    VG_GRAD_RADIAL_STATEMENTS("collections.group.parts.part.description.vector.container.container.container.gradient_radial.")
    /* Task 2.8: inline tree viewbox: property (reuse toplevel handler). */
    {"collections.group.parts.part.description.vector.viewbox", st_vectors_vector_viewbox},
+   /* Task 4.3: target: statement in description-scope override blocks. */
+   {"collections.group.parts.part.description.vector.shape.target",            st_vg_override_target},
+   {"collections.group.parts.part.description.vector.container.target",        st_vg_override_target},
+   {"collections.group.parts.part.description.vector.gradient_linear.target",  st_vg_override_target},
+   {"collections.group.parts.part.description.vector.gradient_radial.target",  st_vg_override_target},
    IMAGE_STATEMENTS("collections.group.parts.part.description.")
    {
       "collections.group.parts.part.description.font", st_fonts_font
@@ -1790,10 +1801,49 @@ _vg_open_node(Edje_Vg_Node_Type type)
    current_vg_node = n;
 }
 
-static void ob_vg_shape(void)           { _vg_open_node(EDJE_VG_NODE_SHAPE); }
-static void ob_vg_container(void)       { _vg_open_node(EDJE_VG_NODE_CONTAINER); }
-static void ob_vg_gradient_linear(void) { _vg_open_node(EDJE_VG_NODE_GRADIENT_LINEAR); }
-static void ob_vg_gradient_radial(void) { _vg_open_node(EDJE_VG_NODE_GRADIENT_RADIAL); }
+static void
+ob_vg_shape(void)
+{
+   if (current_vg_tree && current_vg_node)
+     _vg_open_node(EDJE_VG_NODE_SHAPE);
+   else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+     _vg_open_override(EDJE_VG_NODE_SHAPE);
+   else
+     error_and_abort(NULL, "shape outside vector tree or VECTOR description");
+}
+
+static void
+ob_vg_container(void)
+{
+   if (current_vg_tree && current_vg_node)
+     _vg_open_node(EDJE_VG_NODE_CONTAINER);
+   else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+     _vg_open_override(EDJE_VG_NODE_CONTAINER);
+   else
+     error_and_abort(NULL, "container outside vector tree or VECTOR description");
+}
+
+static void
+ob_vg_gradient_linear(void)
+{
+   if (current_vg_tree && current_vg_node)
+     _vg_open_node(EDJE_VG_NODE_GRADIENT_LINEAR);
+   else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+     _vg_open_override(EDJE_VG_NODE_GRADIENT_LINEAR);
+   else
+     error_and_abort(NULL, "gradient_linear outside vector tree or VECTOR description");
+}
+
+static void
+ob_vg_gradient_radial(void)
+{
+   if (current_vg_tree && current_vg_node)
+     _vg_open_node(EDJE_VG_NODE_GRADIENT_RADIAL);
+   else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+     _vg_open_override(EDJE_VG_NODE_GRADIENT_RADIAL);
+   else
+     error_and_abort(NULL, "gradient_radial outside vector tree or VECTOR description");
+}
 
 static void
 _vg_close_node(void)
@@ -1804,6 +1854,125 @@ _vg_close_node(void)
      current_vg_node = current_vg_tree ? current_vg_tree->root : NULL;
 }
 
+/* Task 4.3: Open an override block at description scope.
+ * Allocates an Edje_Vg_Override, appends it to the description's list,
+ * and routes subsequent property statements into its payload.
+ * target: must be set by st_vg_override_target before description close.
+ * Note: Task 4.4 will replace the append with a merge-or-append path. */
+static void
+_vg_open_override(Edje_Vg_Node_Type type)
+{
+   Edje_Part_Description_Vector *ed;
+   Edje_Vg_Override *ovr;
+
+   if (!current_part || current_part->type != EDJE_PART_TYPE_VECTOR)
+     error_and_abort(NULL, "vector override outside VECTOR description");
+
+   ed = (Edje_Part_Description_Vector *)current_desc;
+
+   ovr = calloc(1, sizeof(Edje_Vg_Override));
+   if (!ovr) error_and_abort(NULL, "OOM allocating override");
+   ovr->expected_type = type;
+   /* payload zeroed; target_name still NULL.
+    * Append happens immediately here; Task 4.4 will swap this for the
+    * merge-aware path once target: fires. */
+   ed->vg.overrides = eina_list_append(ed->vg.overrides, ovr);
+
+   current_vg_override = ovr;
+   current_vg_node = &ovr->payload;
+}
+
+/* Task 4.3: Close either an override block or an inline-tree node block.
+ * When current_vg_override is set we are in override mode: clear the
+ * pointers without touching the container stack (we never pushed).
+ * Otherwise delegate to the existing _vg_close_node. */
+static void
+_vg_close_block(void)
+{
+   if (current_vg_override)
+     {
+        current_vg_override = NULL;
+        current_vg_node = NULL;
+     }
+   else
+     {
+        _vg_close_node();
+     }
+}
+
+/* Task 4.3: Map a node type to a printable string for VEC002 diagnostics. */
+static const char *
+_node_type_str(Edje_Vg_Node_Type t)
+{
+   switch (t)
+     {
+      case EDJE_VG_NODE_SHAPE:           return "shape";
+      case EDJE_VG_NODE_CONTAINER:       return "container";
+      case EDJE_VG_NODE_GRADIENT_LINEAR: return "gradient_linear";
+      case EDJE_VG_NODE_GRADIENT_RADIAL: return "gradient_radial";
+     }
+   return "?";
+}
+
+/* Task 4.3: Validate all override blocks on a VECTOR description at
+ * description-close time.  Emits VEC002 if target is missing, unknown
+ * in the base tree, or type-mismatched. */
+static void
+_vg_finalize_description_overrides(void)
+{
+   Edje_Part_Description_Vector *ed;
+   Eina_Hash *desc_map;
+   Edje_Vg_Tree *base;
+   Eina_List *l;
+   Edje_Vg_Override *ovr;
+
+   if (!current_part || current_part->type != EDJE_PART_TYPE_VECTOR) return;
+   if (!current_desc) return;
+   ed = (Edje_Part_Description_Vector *)current_desc;
+   if (!ed->vg.overrides) return;
+
+   desc_map = _edje_cc_vg_desc_to_tree_get();
+   base = NULL;
+   if (desc_map) base = eina_hash_find(desc_map, &ed);
+
+   if (!base)
+     error_and_abort(NULL,
+        "vector overrides on a description without an active vector tree (VEC002)");
+
+   EINA_LIST_FOREACH(ed->vg.overrides, l, ovr)
+     {
+        Edje_Vg_Node *node;
+
+        if (!ovr->target_name || !*ovr->target_name)
+          error_and_abort(NULL, "vector override missing target: statement");
+        node = _edje_vg_tree_node_by_name(base, ovr->target_name);
+        if (!node)
+          error_and_abort(NULL,
+             "vector override targets unknown node '%s' (VEC002)",
+             ovr->target_name);
+        if (node->type != ovr->expected_type)
+          error_and_abort(NULL,
+             "vector override target '%s' is type %s but override expects %s (VEC002)",
+             ovr->target_name,
+             _node_type_str(node->type),
+             _node_type_str(ovr->expected_type));
+     }
+}
+
+/* Task 4.3: Set the target name for the current override block. */
+static void
+st_vg_override_target(void)
+{
+   const char *s;
+
+   check_arg_count(1);
+   if (!current_vg_override)
+     error_and_abort(NULL, "target: outside vector override block");
+   s = parse_str(0);
+   eina_stringshare_replace(&current_vg_override->target_name, s);
+   free((char *)s);
+}
+
 /**
  * @page edcref
  * @property
@@ -2832,15 +3001,19 @@ New_Object_Handler object_handlers_short[] =
 };
 
 /* Expands to the four node-kind close-pop entries for a given parent path.
- * Fires _vg_close_node when any node block ends, restoring current_vg_node. */
+ * Uses _vg_close_block which delegates to _vg_close_node for inline-tree
+ * contexts and clears the override pointers for description-scope contexts.
+ * Safe for both toplevel vectors{} and description.vector{} prefixes. */
 #define VG_NODE_NESTED_AT(PARENT) \
-   {PARENT, "shape",           NULL, _vg_close_node}, \
-   {PARENT, "container",       NULL, _vg_close_node}, \
-   {PARENT, "gradient_linear", NULL, _vg_close_node}, \
-   {PARENT, "gradient_radial", NULL, _vg_close_node},
+   {PARENT, "shape",           NULL, _vg_close_block}, \
+   {PARENT, "container",       NULL, _vg_close_block}, \
+   {PARENT, "gradient_linear", NULL, _vg_close_block}, \
+   {PARENT, "gradient_radial", NULL, _vg_close_block},
 
 New_Nested_Handler nested_handlers[] = {
    {"collections.group.parts", "part", NULL, edje_cc_handlers_hierarchy_pop },
+   /* Task 4.3: fire VEC002 validation when a description block closes. */
+   {"collections.group.parts.part", "description", NULL, _vg_finalize_description_overrides },
    {"collections.vectors", "vector", NULL, _vg_tree_block_end },
    {"vectors", "vector", NULL, _vg_tree_block_end },
    /* 4-level nesting cap mirrors VG_NODE_OPENERS. */
@@ -9848,6 +10021,22 @@ st_collections_group_parts_part_description_inherit(void)
          ied->vg.id = iparent->vg.id;
          ied->vg.type = iparent->vg.type;
          ied->vg.frame = iparent->vg.frame;
+         /* Task 4.3: propagate parent's base-tree pointer to the child so that
+          * VEC002 validation at description-close can resolve override targets.
+          * The child may later override this with its own vector.use: or
+          * inline vector{} block, which will call _vg_record_use and replace
+          * the entry. */
+         if (_vg_desc_to_tree)
+           {
+              Edje_Vg_Tree *parent_tree = eina_hash_find(_vg_desc_to_tree, &iparent);
+              if (parent_tree)
+                {
+                   /* Use set/del to handle the case where a prior inherit
+                    * already populated ied's entry (can't happen today but
+                    * safe in general). */
+                   eina_hash_set(_vg_desc_to_tree, &ied, parent_tree);
+                }
+           }
          break;
       }
      }
diff --git a/src/tests/edje/data/test_vector_states.edc b/src/tests/edje/data/test_vector_states.edc
index 12a4b69bd7..69617c45d0 100644
--- a/src/tests/edje/data/test_vector_states.edc
+++ b/src/tests/edje/data/test_vector_states.edc
@@ -38,4 +38,23 @@ collections {
          }
       } }
    }
+   /* Task 4.3: override authoring fixture.
+    * The hover description references tile_a (inherited from default) and
+    * overrides the "body" shape's fill and stroke. */
+   group { name: "ui/box_a_hover";
+      parts { part { name: "vg"; type: VECTOR;
+         description { state: "default" 0.0;
+            vector.use: "tile_a";
+         }
+         description { state: "hover" 0.0;
+            inherit: "default" 0.0;
+            vector.shape {
+               target: "body";
+               fill.color: 200 200 0 255;
+               stroke.color: 30 30 30 255;
+               stroke.width: 4;
+            }
+         }
+      } }
+   }
 }

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to