Skip to content

Conversation

@senithkay
Copy link
Contributor

@senithkay senithkay commented Jan 28, 2026

Purpose

Recursive type creation was not correctly updating the field type with the newly created type name. When a type was created from within a field (recursive flow), the editor failed to propagate the saved type name back to the originating field, leaving the field type in an inconsistent or default state.
This resulted in broken recursive type definitions and incorrect type graphs.

Resolves: wso2/product-ballerina-integrator#1740

Goals

  • Ensure fields involved in recursive type creation are updated with the newly saved type name.
  • Preserve correct field–type associations across nested and recursive type creation flows.
  • Improve the overall reliability and correctness of recursive type handling.

Approach

  • Track the originating field using a fieldIndex when initiating recursive type creation.
  • Store this index in the type creation stack to maintain context across nested type creation steps.
  • When a type is saved, use the tracked fieldIndex to identify the correct field in the stack.
  • Update the corresponding field’s type with the newly created type name before unwinding the stack.
  • This ensures that recursive and nested type creation flows correctly resolve and reflect the final type names.

Summary by CodeRabbit

  • New Features

    • Enhanced support for creating and editing nested types with improved field-level tracking and management.
    • Strengthened type stack handling across all editors for more robust and consistent type creation workflows.
  • Refactor

    • Optimized type editor architecture to support field index propagation throughout the type creation process.
    • Updated component interfaces for better field identification in nested type operations.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

Walkthrough

This PR introduces fieldIndex tracking to support nested type creation within the type editor system. When users create new types for specific fields, the fieldIndex is now preserved through stack operations and propagated upward when saving, enabling parent types to correctly update their field references with the newly created child types.

Changes

Cohort / File(s) Summary
Visualizer Form Generators
workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx, FormGeneratorNew/index.tsx
Extended getNewTypeCreateForm to accept optional fieldIndex, preserve fieldIndex when replacing stack items, and enhance onSaveType to propagate type names to parent stack items based on parent type (CLASS vs function), then pop the stack
TypeEditor Props Update
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsx
Updated getNewTypeCreateForm public signature to accept optional fieldIndex as first parameter, adjusted internal handleTypeCreate to forward both parameters
GraphQL & Type Diagram Views
workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx, TypeDiagram/index.tsx
Extended getNewTypeCreateForm with fieldIndex support, enhanced stack replacement to preserve fieldIndex, refactored onSaveType to conditionally propagate types up the stack, moved Type editing panel into EditorContext.Provider in TypeDiagram
Type Editor Context
workspaces/ballerina/type-editor/src/Context/index.tsx, TypeEditor/Contexts/TypeEditorContext.ts
Updated onTypeCreate callback signature to require fieldIndex: number parameter, added optional fieldIndex?: number property to StackItem interface
Type Field Components
workspaces/ballerina/type-editor/src/TypeEditor/TypeField.tsx, FieldEditor.tsx
Added fieldIndex prop to TypeFieldProps and FieldEditorProps, propagate fieldIndex through component chain and pass to onTypeCreate invocation
Editor Components
workspaces/ballerina/type-editor/src/TypeEditor/ArrayEditor.tsx, ClassEditor.tsx, UnionEditor.tsx
Added fieldIndex prop to TypeField invocations, passing current field/parameter index for context-aware type creation
Record & Schema Editors
workspaces/ballerina/type-editor/src/TypeEditor/RecordEditor.tsx, ContextBasedTypeEditor/SchemaRecordEditor.tsx
Added index prop to FieldEditor invocations to expose field position information
Context-Based Type Editor
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/ContextTypeEditor.tsx, ContextTypeCreator.tsx
Updated onTypeCreate callback signature in props, added onTypeChange side-effect notification in handleSetType
TypeEditor Props
workspaces/ballerina/type-editor/src/TypeEditor/TypeEditor.tsx
Updated onTypeCreate callback signature to include required fieldIndex: number parameter

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Editor as Type Editor
    participant Stack as Type Stack Manager
    participant Parent as Parent Type
    participant Field as Field Handler

    User->>Editor: Click "Create nested type" for field
    Editor->>Stack: getNewTypeCreateForm(fieldIndex, typeName?)
    Stack->>Stack: Preserve fieldIndex on current top
    Stack->>Stack: Push new type creation frame
    Stack->>Editor: Render nested type form
    
    User->>Editor: Fill nested type details
    User->>Editor: Save nested type
    
    Editor->>Stack: onSaveType(type)
    Stack->>Stack: Check if stack.length > 1
    alt Parent exists on stack
        Stack->>Parent: Retrieve parent from stack
        Stack->>Field: Determine field type (returnType vs member)
        Field->>Parent: Update field at fieldIndex with type name
        Stack->>Stack: Update parent in stack
        Stack->>Stack: Pop nested type from top
    else No parent
        Stack->>Stack: Pop type
    end
    
    Stack->>Editor: Refresh state with updated stack
    Editor->>User: Nested type created and field updated
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 Hop along, dear types so fine,
Stack by stack, your fields align!
With fieldIndex, we nest with grace,
Parent knows each type's true place!
Recursive creation, now complete,
Makes our type editor oh-so-sweet! 🌟

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Fix recursive type creation iss' is vague and incomplete; 'iss' appears truncated and does not clearly describe the change. Complete the title to accurately describe the fix, e.g., 'Fix recursive type creation to propagate field types' or 'Fix recursive type creation field type updates'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description adequately covers Purpose, Goals, and Approach sections with specific details about the fix, problem context, and solution strategy.
Linked Issues check ✅ Passed The code changes successfully implement the requirements from issue #1740 by introducing fieldIndex tracking, stack propagation, and type name updates during recursive type creation across multiple components.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing recursive type creation fixes by propagating fieldIndex through the type creation stack and updating field types appropriately.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@kanushka
Copy link
Contributor

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/ContextTypeCreator.tsx (1)

193-200: Avoid duplicate onTypeChange during rename.

handleSetType() now triggers onTypeChange, but editTypeName already calls onTypeChange(renamedType, true), so renames will emit two change events. Consider adding a flag to skip the default notification when a rename-specific notification will follow.

🛠️ Suggested adjustment
-    const handleSetType = (type: Type) => {
-        onTypeChange(type);
+    const handleSetType = (type: Type, notifyChange = true) => {
+        if (notifyChange) {
+            onTypeChange(type);
+        }
         replaceTop({
             type: type,
             isDirty: true
         })
         setType(type);
     }
-            handleSetType(renamedType);
-            onTypeChange(renamedType, true);
+            handleSetType(renamedType, false);
+            onTypeChange(renamedType, true);
workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx (1)

317-327: Preserve fieldIndex when it is 0.

The current truthy check drops index 0, so the first field loses its association and later propagation can fail. Use a nullish check instead.

🧩 Proposed fix
-            if (newStack[newStack.length - 1].fieldIndex) {
-                item.fieldIndex = newStack[newStack.length - 1].fieldIndex;
-            }
+            const prevFieldIndex = newStack[newStack.length - 1].fieldIndex;
+            if (prevFieldIndex !== undefined) {
+                item.fieldIndex = prevFieldIndex;
+            }
workspaces/ballerina/type-editor/src/Context/index.tsx (1)

47-52: Fix default onTypeCreate value to match the updated signature requiring fieldIndex.

The default in Context/index.tsx (line 66) is onTypeCreate: () => {}, which doesn't satisfy the new signature (fieldIndex: number, typeName?: string) => void declared at line 51. Update the default to accept the fieldIndex parameter: onTypeCreate: () => Promise.resolve({} as AddImportItemResponse) or an appropriate no-op that accepts the parameters. All call sites in TypeField.tsx properly pass fieldIndex; the issue is only with the default fallback value.

workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx (1)

136-143: Preserve fieldIndex when it is 0.

The truthy check skips index 0, so the first field loses its index and later updates can target the wrong member (or crash). Use an explicit undefined check.

🛠️ Suggested fix
-            if (newStack[newStack.length - 1].fieldIndex) {
-                item.fieldIndex = newStack[newStack.length - 1].fieldIndex;
-            }
+            const prevFieldIndex = newStack[newStack.length - 1].fieldIndex;
+            if (prevFieldIndex !== undefined) {
+                item.fieldIndex = prevFieldIndex;
+            }
workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx (1)

284-291: Preserve fieldIndex when it is 0.

The truthy check drops index 0, which can break updates for the first member/function. Use an explicit undefined check.

🛠️ Suggested fix
-            if (newStack[newStack.length - 1].fieldIndex) {
-                item.fieldIndex = newStack[newStack.length - 1].fieldIndex;
-            }
+            const prevFieldIndex = newStack[newStack.length - 1].fieldIndex;
+            if (prevFieldIndex !== undefined) {
+                item.fieldIndex = prevFieldIndex;
+            }
workspaces/ballerina/type-editor/src/TypeEditor/TypeField.tsx (1)

29-43: Prevent undefined fieldIndex from reaching onTypeCreate.

fieldIndex is optional here, but onTypeCreate now expects a number. With non‑strict null checks, undefined can slip through and mis-associate the created type with the wrong field. Prefer making fieldIndex required (or explicitly guard and surface an error when missing).

✅ Suggested fix (make fieldIndex required)
 interface TypeFieldProps {
     type: string | Type;
     memberName: string;
     onChange: (value: string) => void;
     onUpdateImports: (imports: Imports) => void;
     placeholder?: string;
     sx?: React.CSSProperties;
     onValidationError?: (isError: boolean) => void;
     rootType: Type;
     isAnonymousRecord?: boolean;
     label?: string;
     required?: boolean;
     autoFocus?: boolean;
-    fieldIndex?: number;
+    fieldIndex: number;
 }

Also applies to: 209-212

🤖 Fix all issues with AI agents
In
`@workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx`:
- Around line 1308-1314: The function getNewTypeCreateForm currently mutates the
object returned by peekTypeStack and unconditionally assigns fieldIndex which
can overwrite an existing index with undefined; instead, when currentTopItem
exists only set fieldIndex if the incoming fieldIndex is not undefined and avoid
in-place mutation—create a shallow copy of currentTopItem, set copy.fieldIndex =
fieldIndex only when fieldIndex !== undefined, then call replaceTop(copy); leave
pushTypeStack(getDefaultValue(typeName)) unchanged.
- Around line 1083-1100: The onSaveType handler mutates newTop by indexing
newTop.fieldIndex into newTop.type.functions or newTop.type.members without
checking that fieldIndex is defined and within bounds; add a defensive guard in
onSaveType: verify newTop.fieldIndex is a finite number and between 0 and the
length-1 of the appropriate array (newTop.type.functions for CLASS, otherwise
newTop.type.members) before assigning returnType/type, and bail out or skip the
assignment if the guard fails; keep the rest of the flow (updating newStack,
popping, setStack, setRefetchForCurrentModal) unchanged.

In
`@workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx`:
- Around line 367-377: In onSaveType, guard access to newTop.fieldIndex and
newTop.type.members before assigning: verify newTop.fieldIndex is a valid number
and that newTop.type and Array.isArray(newTop.type.members) are present and
newTop.fieldIndex is within bounds (0 <= fieldIndex < members.length); only then
perform newTop.type.members[newTop.fieldIndex].type = currentTop!.type.name and
update/pop the newStack via setStack; if the guard fails, handle gracefully
(skip the assignment and still adjust stack or log/return) to avoid exceptions
from missing/out-of-range indexes.

In `@workspaces/ballerina/ballerina-visualizer/src/views/TypeDiagram/index.tsx`:
- Around line 127-134: The current replaceTop function drops a fieldIndex of 0
due to a truthy check; update the conditional in replaceTop (operating on
StackItem and setStack) to test explicitly for undefined (e.g., !== undefined or
typeof ... !== 'undefined') when copying newStack[newStack.length -
1].fieldIndex into item.fieldIndex so zero is preserved.

Comment on lines 1083 to 1100
const onSaveType = (type: Type | string) => {
handleValueTypeConstChange(typeof type === 'string' ? type : (type as Type).name);
if (stack.length > 0) {
if (stack.length > 1) {
const newStack = [...stack]
const currentTop = newStack[newStack.length - 1];
const newTop = newStack[newStack.length - 2];
if (newTop.type.codedata.node === "CLASS") {
newTop.type.functions[newTop.fieldIndex!].returnType = currentTop!.type.name;
}
else {
newTop.type.members[newTop.fieldIndex!].type = currentTop!.type.name;
}
newStack[newStack.length - 2] = newTop;
newStack.pop();
setStack(newStack);
}
setRefetchForCurrentModal(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard against missing/out-of-range fieldIndex before indexing.

fieldIndex is optional and currently asserted non-null. If it’s undefined (or out of bounds), this will throw when accessing functions[...] or members[...]. Add a defensive guard to avoid runtime errors.

🧩 Suggested guard
-                if (newTop.type.codedata.node === "CLASS") {
-                    newTop.type.functions[newTop.fieldIndex!].returnType = currentTop!.type.name;
-                }
-                else {
-                    newTop.type.members[newTop.fieldIndex!].type = currentTop!.type.name;
-                }
+                const fieldIndex = newTop.fieldIndex;
+                if (fieldIndex === undefined) {
+                    return;
+                }
+                if (newTop.type.codedata.node === "CLASS") {
+                    const fn = newTop.type.functions?.[fieldIndex];
+                    if (!fn) { return; }
+                    fn.returnType = currentTop!.type.name;
+                } else {
+                    const member = newTop.type.members?.[fieldIndex];
+                    if (!member) { return; }
+                    member.type = currentTop!.type.name;
+                }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const onSaveType = (type: Type | string) => {
handleValueTypeConstChange(typeof type === 'string' ? type : (type as Type).name);
if (stack.length > 0) {
if (stack.length > 1) {
const newStack = [...stack]
const currentTop = newStack[newStack.length - 1];
const newTop = newStack[newStack.length - 2];
if (newTop.type.codedata.node === "CLASS") {
newTop.type.functions[newTop.fieldIndex!].returnType = currentTop!.type.name;
}
else {
newTop.type.members[newTop.fieldIndex!].type = currentTop!.type.name;
}
newStack[newStack.length - 2] = newTop;
newStack.pop();
setStack(newStack);
}
setRefetchForCurrentModal(true);
const onSaveType = (type: Type | string) => {
handleValueTypeConstChange(typeof type === 'string' ? type : (type as Type).name);
if (stack.length > 0) {
if (stack.length > 1) {
const newStack = [...stack]
const currentTop = newStack[newStack.length - 1];
const newTop = newStack[newStack.length - 2];
const fieldIndex = newTop.fieldIndex;
if (fieldIndex === undefined) {
return;
}
if (newTop.type.codedata.node === "CLASS") {
const fn = newTop.type.functions?.[fieldIndex];
if (!fn) { return; }
fn.returnType = currentTop!.type.name;
} else {
const member = newTop.type.members?.[fieldIndex];
if (!member) { return; }
member.type = currentTop!.type.name;
}
newStack[newStack.length - 2] = newTop;
newStack.pop();
setStack(newStack);
}
setRefetchForCurrentModal(true);
🤖 Prompt for AI Agents
In
`@workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx`
around lines 1083 - 1100, The onSaveType handler mutates newTop by indexing
newTop.fieldIndex into newTop.type.functions or newTop.type.members without
checking that fieldIndex is defined and within bounds; add a defensive guard in
onSaveType: verify newTop.fieldIndex is a finite number and between 0 and the
length-1 of the appropriate array (newTop.type.functions for CLASS, otherwise
newTop.type.members) before assigning returnType/type, and bail out or skip the
assignment if the guard fails; keep the rest of the flow (updating newStack,
popping, setStack, setRefetchForCurrentModal) unchanged.

Comment on lines +1308 to 1314
const getNewTypeCreateForm = (fieldIndex?: number, typeName?: string) => {
const currentTopItem = peekTypeStack();
if (currentTopItem) {
currentTopItem.fieldIndex = fieldIndex;
replaceTop(currentTopItem);
}
pushTypeStack(getDefaultValue(typeName));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid clearing an existing fieldIndex when none is provided.

Because fieldIndex is optional, assigning it unconditionally can overwrite a previously stored index with undefined. Guard the assignment (and avoid mutating state objects in place).

🧩 Proposed fix
-        if (currentTopItem) {
-            currentTopItem.fieldIndex = fieldIndex;
-            replaceTop(currentTopItem);
-        }
+        if (currentTopItem && fieldIndex !== undefined) {
+            replaceTop({ ...currentTopItem, fieldIndex });
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getNewTypeCreateForm = (fieldIndex?: number, typeName?: string) => {
const currentTopItem = peekTypeStack();
if (currentTopItem) {
currentTopItem.fieldIndex = fieldIndex;
replaceTop(currentTopItem);
}
pushTypeStack(getDefaultValue(typeName));
const getNewTypeCreateForm = (fieldIndex?: number, typeName?: string) => {
const currentTopItem = peekTypeStack();
if (currentTopItem && fieldIndex !== undefined) {
replaceTop({ ...currentTopItem, fieldIndex });
}
pushTypeStack(getDefaultValue(typeName));
🤖 Prompt for AI Agents
In
`@workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx`
around lines 1308 - 1314, The function getNewTypeCreateForm currently mutates
the object returned by peekTypeStack and unconditionally assigns fieldIndex
which can overwrite an existing index with undefined; instead, when
currentTopItem exists only set fieldIndex if the incoming fieldIndex is not
undefined and avoid in-place mutation—create a shallow copy of currentTopItem,
set copy.fieldIndex = fieldIndex only when fieldIndex !== undefined, then call
replaceTop(copy); leave pushTypeStack(getDefaultValue(typeName)) unchanged.

Comment on lines 367 to +377
const onSaveType = () => {
if (stack.length > 0) {
if (stack.length > 1) {
const newStack = [...stack]
const currentTop = newStack[newStack.length - 1];
const newTop = newStack[newStack.length - 2];
newTop.type.members[newTop.fieldIndex!].type = currentTop!.type.name;
newStack[newStack.length - 2] = newTop;
newStack.pop();
setStack(newStack);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard fieldIndex/member existence before assignment.

newTop.fieldIndex! and newTop.type.members[...] can throw if the index is missing or out of range (e.g., due to a dropped 0). Add a defensive check before writing.

🛠️ Suggested fix
-                newTop.type.members[newTop.fieldIndex!].type = currentTop!.type.name;
+                const fieldIndex = newTop.fieldIndex;
+                if (fieldIndex === undefined || !newTop.type?.members?.[fieldIndex]) {
+                    return;
+                }
+                newTop.type.members[fieldIndex].type = currentTop.type.name;
🤖 Prompt for AI Agents
In `@workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx`
around lines 367 - 377, In onSaveType, guard access to newTop.fieldIndex and
newTop.type.members before assigning: verify newTop.fieldIndex is a valid number
and that newTop.type and Array.isArray(newTop.type.members) are present and
newTop.fieldIndex is within bounds (0 <= fieldIndex < members.length); only then
perform newTop.type.members[newTop.fieldIndex].type = currentTop!.type.name and
update/pop the newStack via setStack; if the guard fails, handle gracefully
(skip the assignment and still adjust stack or log/return) to avoid exceptions
from missing/out-of-range indexes.

Comment on lines 127 to +134
const replaceTop = (item: StackItem) => {
if (stack.length <= 1) return;
if (stack.length === 0) return;
setStack((prev) => {
const newStack = [...prev];
//preserve fieldIndex if exists
if (newStack[newStack.length - 1].fieldIndex) {
item.fieldIndex = newStack[newStack.length - 1].fieldIndex;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve fieldIndex when it is 0.

The truthy check drops index 0, which breaks updates for the first field. Use an explicit undefined check.

🛠️ Suggested fix
-            if (newStack[newStack.length - 1].fieldIndex) {
-                item.fieldIndex = newStack[newStack.length - 1].fieldIndex;
-            }
+            const prevFieldIndex = newStack[newStack.length - 1].fieldIndex;
+            if (prevFieldIndex !== undefined) {
+                item.fieldIndex = prevFieldIndex;
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const replaceTop = (item: StackItem) => {
if (stack.length <= 1) return;
if (stack.length === 0) return;
setStack((prev) => {
const newStack = [...prev];
//preserve fieldIndex if exists
if (newStack[newStack.length - 1].fieldIndex) {
item.fieldIndex = newStack[newStack.length - 1].fieldIndex;
}
const replaceTop = (item: StackItem) => {
if (stack.length === 0) return;
setStack((prev) => {
const newStack = [...prev];
//preserve fieldIndex if exists
const prevFieldIndex = newStack[newStack.length - 1].fieldIndex;
if (prevFieldIndex !== undefined) {
item.fieldIndex = prevFieldIndex;
}
🤖 Prompt for AI Agents
In `@workspaces/ballerina/ballerina-visualizer/src/views/TypeDiagram/index.tsx`
around lines 127 - 134, The current replaceTop function drops a fieldIndex of 0
due to a truthy check; update the conditional in replaceTop (operating on
StackItem and setStack) to test explicitly for undefined (e.g., !== undefined or
typeof ... !== 'undefined') when copying newStack[newStack.length -
1].fieldIndex into item.fieldIndex so zero is preserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants