Skip to content

fix: Global variables support - types and debugger mapping#520

Merged
thiagoralves merged 3 commits into
developmentfrom
fix/global-variables-all-types
Jan 10, 2026
Merged

fix: Global variables support - types and debugger mapping#520
thiagoralves merged 3 commits into
developmentfrom
fix/global-variables-all-types

Conversation

@thiagoralves
Copy link
Copy Markdown
Contributor

@thiagoralves thiagoralves commented Jan 10, 2026

Summary

  • Add all variable types (function blocks, arrays) to global variables table
  • Fix debugger to correctly map external variables to their corresponding global variables

Changes

1. Global Variables Table Enhancements

  • Added function block types (system and user libraries) to global variable type dropdown
  • Added array type support with GlobalArrayModal component
  • Added search/filter functionality for all type categories

2. Debugger External → Global Variable Mapping

When forcing or viewing an external variable in a POU, the debugger now correctly maps it to the corresponding global variable (CONFIG0__ prefix) instead of looking for a local POU variable (RES0__ prefix).

Files changed:

  • src/renderer/utils/parse-debug-file.ts - Added variableClass parameter to handle external variables
  • src/renderer/utils/debug-tree-builder.ts - Added buildVariableBasePath helper for correct path construction
  • src/renderer/components/_organisms/workspace-activity-bar/default.tsx - Pass variable class to matching function
  • src/renderer/components/_molecules/global-variables-table/ - New array modal and enhanced type selector

Why This Matters

Previously:

  • Global variables could only be base types or user data types
  • External variables in POUs couldn't be properly forced/viewed in debugger
  • Forcing an external variable in one POU didn't affect other POUs

Now:

  • Global variables support all types including function blocks and arrays
  • External variables correctly map to CONFIG0__VARNAME in debug.c
  • Forcing an external variable affects the actual global variable across all POUs

Related

Requires xml2st fix: Autonomy-Logic/xml2st#24

Test plan

  • Create global variable of type ARRAY
  • Create global variable of type function block (e.g., TON, PID)
  • Create global array of function blocks
  • Compile project and verify no errors
  • Debug project and verify external variables can be forced
  • Verify forcing external variable in one POU reflects in others

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a modal for editing global array variables with dimension management and validation.
    • Introduced searchable, categorized type selection menus (base types, user types, system/user libraries).
  • Improvements

    • More reliable debug variable matching and path resolution across external and local variables.
    • Improved variable-to-debug mapping to better align debug entries with variables.

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

thiagoralves and others added 2 commits January 9, 2026 20:32
Bring the same types from program POU variable table to global variables:
- Add function block types (system and user libraries)
- Add array type support with GlobalArrayModal
- Add search/filter functionality for all type categories

This matches the functionality available in the regular POU variable table.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When forcing or viewing an external variable in a POU, the debugger
now correctly maps it to the corresponding global variable (CONFIG0__
prefix) instead of looking for a local POU variable (RES0__ prefix).

This ensures that:
- Forcing an external variable affects the actual global variable
- All POUs with the same external variable see the same value
- Global variables can be properly debugged

Changes:
- Updated matchVariableWithDebugEntry to handle external variables
- Added matchGlobalVariableWithDebugEntry for direct global var matching
- Updated buildDebugTree and related functions to use correct paths
  for external variables (CONFIG0__ vs RES0__)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 10, 2026

Walkthrough

Adds a GlobalArrayModal component and integrates it into the type-selection UI; introduces categorized, searchable type and library submenus; centralizes variable base-path computation and extends debug-variable matching to handle external/global variables.

Changes

Cohort / File(s) Summary
Global Array Modal Component
src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx
New exported GlobalArrayModal component and ArrayModalProps usage: reads store data, builds categorized type lists, manages dimension state, validates arrays, and calls updateVariable on save via DimensionsModal.
Type Selection UI Integration
src/renderer/components/_molecules/global-variables-table/selectable-cell.tsx
Integrates GlobalArrayModal; replaces flat type list with searchable submenus for VariableTypes (base vs user-data) and LibraryTypes (system vs user); adds filtering state, array-modal visibility, and preserves two-step type-change validation flow.
Debug Utilities Refactor
src/renderer/utils/debug-tree-builder.ts, src/renderer/utils/parse-debug-file.ts
Introduces buildVariableBasePath to unify fullPath construction; updates matchVariableWithDebugEntry signature to accept optional variableClass; adds matchGlobalVariableWithDebugEntry for CONFIG0__ prefix matching.
Debug Integration Update
src/renderer/components/_organisms/workspace-activity-bar/default.tsx
Passes v.class into matchVariableWithDebugEntry calls to allow external/global-aware matching when building the activity-bar index map.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant SelectableTypeCell
    participant GlobalArrayModal
    participant DimensionsModal
    participant OpenPLC_Store

    User->>SelectableTypeCell: Click "Array"
    SelectableTypeCell->>GlobalArrayModal: open(arrayModalIsOpen, variableName)
    GlobalArrayModal->>OpenPLC_Store: read globalVariables, dataTypes, libraries
    OpenPLC_Store-->>GlobalArrayModal: return variable & type data
    GlobalArrayModal->>DimensionsModal: render with categorized types & handlers
    User->>DimensionsModal: edit dimensions / select base type
    DimensionsModal-->>GlobalArrayModal: emit dimension/type updates
    User->>GlobalArrayModal: Save
    GlobalArrayModal->>GlobalArrayModal: validate & format array type
    GlobalArrayModal->>OpenPLC_Store: updateVariable(new array-type payload)
    OpenPLC_Store-->>GlobalArrayModal: confirm
    GlobalArrayModal->>SelectableTypeCell: close modal / propagate close
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

bug, enhancement

Suggested reviewers

  • JoaoGSP
  • vmleroy
  • JulioSergioFS

Poem

🐰 I hopped into arrays with a curious grin,
Types sorted in nests, and dimensions to spin,
I matched external paths beneath debug trees,
Saved with a thump and a carrot-y breeze,
Hooray — arrays snug, and the code hops in! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: global variables type support and debugger mapping fixes for external variables.
Description check ✅ Passed The description includes summary, detailed changes, file list, and test plan, but the DOD checklist is incomplete with no items marked complete.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.

✏️ 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.

Copy link
Copy Markdown
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: 1

🤖 Fix all issues with AI agents
In
@src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx:
- Around line 93-106: handleRearrangeDimensions is mutating the dimensions array
with splice; change it to perform immutable updates instead: create a copy of
dimensions (e.g., [...dimensions]), remove and insert the item in the copy using
non-mutating operations (slice/spread), then call setDimensions(newDimensions)
and setSelectedInput with the new index string; keep the same boundary checks
and use the same function name handleRearrangeDimensions and state setters
(setDimensions, setSelectedInput).
🧹 Nitpick comments (1)
src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx (1)

142-145: Consider simplifying base type check.

The forEach loop can be replaced with a more concise includes() check for improved readability.

♻️ Suggested simplification
-    let isBaseType = false
-    baseTypes.forEach((type) => {
-      if (type === typeValue) isBaseType = true
-    })
+    const isBaseType = baseTypes.includes(typeValue)
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6b3b50a and 4cf15f4.

📒 Files selected for processing (5)
  • src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx
  • src/renderer/components/_molecules/global-variables-table/selectable-cell.tsx
  • src/renderer/components/_organisms/workspace-activity-bar/default.tsx
  • src/renderer/utils/debug-tree-builder.ts
  • src/renderer/utils/parse-debug-file.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-16T14:31:51.786Z
Learnt from: vmleroy
Repo: Autonomy-Logic/openplc-editor PR: 265
File: src/renderer/components/_atoms/graphical-editor/ladder/block.tsx:149-153
Timestamp: 2025-06-16T14:31:51.786Z
Learning: In src/renderer/components/_atoms/graphical-editor/ladder/block.tsx, the libraries.system data is dynamic and imported from JSON with varying structure, making proper static typing infeasible. The ts-expect-error and eslint-disable comments are justified when dynamically probing the structure at runtime.

Applied to files:

  • src/renderer/components/_molecules/global-variables-table/selectable-cell.tsx
📚 Learning: 2025-03-14T14:46:03.671Z
Learnt from: JoaoGSP
Repo: Autonomy-Logic/openplc-editor PR: 218
File: src/renderer/components/_atoms/graphical-editor/fbd/variable.tsx:73-73
Timestamp: 2025-03-14T14:46:03.671Z
Learning: Empty useEffect hooks in the VariableElement component (src/renderer/components/_atoms/graphical-editor/fbd/variable.tsx) are intentional placeholders that will be implemented later as they depend on other logic.

Applied to files:

  • src/renderer/components/_molecules/global-variables-table/selectable-cell.tsx
🧬 Code graph analysis (3)
src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx (6)
src/renderer/store/index.ts (1)
  • useOpenPLCStore (91-91)
src/shared/data/common.ts (1)
  • baseTypes (34-34)
src/types/PLC/open-plc.ts (1)
  • BaseType (445-445)
src/renderer/store/slices/project/validation/variables.ts (1)
  • arrayValidation (531-531)
src/renderer/components/_features/[app]/toast/use-toast.tsx (1)
  • toast (240-240)
src/renderer/components/_atoms/dimensions-modal/index.tsx (1)
  • DimensionsModal (36-160)
src/renderer/components/_molecules/global-variables-table/selectable-cell.tsx (2)
src/types/PLC/open-plc.ts (2)
  • PLCGlobalVariable (460-460)
  • PLCVariable (474-474)
src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx (1)
  • GlobalArrayModal (20-194)
src/renderer/components/_organisms/workspace-activity-bar/default.tsx (1)
src/renderer/utils/parse-debug-file.ts (1)
  • matchVariableWithDebugEntry (125-148)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: build (windows-latest)
  • GitHub Check: build (macos-latest)
  • GitHub Check: test (macos-latest)
  • GitHub Check: test (windows-latest)
  • GitHub Check: test (ubuntu-latest)
🔇 Additional comments (11)
src/renderer/components/_organisms/workspace-activity-bar/default.tsx (1)

888-888: LGTM! Proper integration with enhanced variable matching.

The addition of v.class as the fourth parameter correctly aligns with the updated matchVariableWithDebugEntry signature, enabling the debugger to distinguish external variables and map them to the correct global entries (CONFIG0__ prefix).

src/renderer/utils/debug-tree-builder.ts (2)

47-60: LGTM! Excellent refactoring for centralized path construction.

The buildVariableBasePath helper consolidates the logic for determining variable paths based on class (external vs. local), eliminating duplication and ensuring consistent handling of the CONFIG0__ vs. RES0__ prefix across the codebase.


86-86: LGTM! Consistent usage of the new helper.

All call sites correctly delegate path construction to buildVariableBasePath, passing the appropriate variableClass when available.

Also applies to: 107-107, 142-142, 580-580, 669-669

src/renderer/utils/parse-debug-file.ts (2)

125-148: LGTM! Correct implementation of external variable matching.

The extended signature with optional variableClass parameter and the new branch for external variables correctly implement the mapping to global debug entries (CONFIG0__ prefix), ensuring the debugger resolves external POU variables to the actual global variables.


150-164: LGTM! Clear and focused helper for global variable matching.

The new matchGlobalVariableWithDebugEntry function provides a clean API for directly matching global variables with their debug entries using the CONFIG0__ prefix.

src/renderer/components/_molecules/global-variables-table/selectable-cell.tsx (4)

68-87: LGTM! Comprehensive library type extraction.

The LibraryTypes definition correctly extracts function blocks from both system and user libraries, handling the variation in structure (libraries with POUs arrays vs. single function blocks).

Based on learnings, the runtime type checking with 'pous' in userLibrary is appropriate given the dynamic library structure.


205-211: LGTM! Clean integration of array modal.

The GlobalArrayModal component is properly wired with state management and the closeContainer callback ensures the dropdown closes when the modal is opened.


234-305: LGTM! Enhanced UX with searchable submenus.

The multi-submenu structure with search/filter capability significantly improves the user experience for selecting variable types. The implementation correctly:

  • Provides per-definition search filtering
  • Displays appropriate "No ... found" messages
  • Opens the array modal as a menu item
  • Resets filters on submenu close

307-357: LGTM! Consistent pattern for library submenus.

The library type submenus (system and user) follow the same searchable pattern as the variable type submenus, providing a consistent UI experience. The selection correctly uses 'derived' as the definition for library function blocks.

src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx (2)

155-155: Type suppression comment indicates pending type fix.

The @ts-expect-error comment at Line 155 suggests a known type mismatch that the team is tracking. Ensure this is addressed in follow-up work to maintain type safety.

Is there an issue tracking the resolution of this type error?


40-64: LGTM! Solid array modal implementation.

The component correctly:

  • Extracts base types, user data types, and function blocks from libraries
  • Initializes state from existing global variables
  • Validates dimensions before saving
  • Constructs proper array type definitions with base type classification
  • Integrates cleanly with the store's updateVariable action

Also applies to: 70-81, 130-167

@thiagoralves thiagoralves requested a review from Copilot January 10, 2026 04:36
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for function block and array types to global variables, and fixes the debugger to correctly map external variables to their corresponding global variables (using CONFIG0__ prefix instead of RES0__ prefix).

Changes:

  • Enhanced global variables table with function block types (system/user libraries) and array support
  • Fixed debugger mapping for external variables to use CONFIG0__ prefix for global variables
  • Added search/filter functionality to the type selector dropdown

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/renderer/utils/parse-debug-file.ts Added handling for external variables to map to global variables with CONFIG0__ prefix
src/renderer/utils/debug-tree-builder.ts Refactored path construction with new buildVariableBasePath helper function
src/renderer/components/_organisms/workspace-activity-bar/default.tsx Updated to pass variable class parameter to matching function
src/renderer/components/_molecules/global-variables-table/selectable-cell.tsx Added library types and array support to type selector with search functionality
src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx New modal component for creating/editing array global variables

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

definition: 'array',
value: formatArrayName,
data: {
// @ts-expect-error - This is a valid operation. This is being fixed.
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

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

The ts-expect-error comment lacks specificity about what is being fixed and when. Consider adding more context such as a ticket number or a more detailed explanation of the type mismatch.

Suggested change
// @ts-expect-error - This is a valid operation. This is being fixed.
// @ts-expect-error - `type.data` in the variable schema does not currently declare a `baseType`
// field, but PLC array types expect this shape at runtime. This suppression can be removed once
// the TypeScript definitions for global variable `type.data` are updated to include `baseType`.

Copilot uses AI. Check for mistakes.
Comment on lines +93 to +105
const handleRearrangeDimensions = (index: number, direction: 'up' | 'down') => {
if (direction === 'up') {
if (index === 0) return
const [removed] = dimensions.splice(index, 1)
dimensions.splice(index - 1, 0, removed)
setSelectedInput((index - 1).toString())
return
}

if (index === dimensions.length - 1) return
const [removed] = dimensions.splice(index, 1)
dimensions.splice(index + 1, 0, removed)
setSelectedInput((index + 1).toString())
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

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

The variable name removed is reused in both the 'up' and 'down' branches with the same splice operation. Consider extracting the common logic into a helper function or variable to reduce duplication.

Suggested change
const handleRearrangeDimensions = (index: number, direction: 'up' | 'down') => {
if (direction === 'up') {
if (index === 0) return
const [removed] = dimensions.splice(index, 1)
dimensions.splice(index - 1, 0, removed)
setSelectedInput((index - 1).toString())
return
}
if (index === dimensions.length - 1) return
const [removed] = dimensions.splice(index, 1)
dimensions.splice(index + 1, 0, removed)
setSelectedInput((index + 1).toString())
const moveDimension = (fromIndex: number, toIndex: number) => {
const [removed] = dimensions.splice(fromIndex, 1)
dimensions.splice(toIndex, 0, removed)
setSelectedInput(toIndex.toString())
}
const handleRearrangeDimensions = (index: number, direction: 'up' | 'down') => {
if (direction === 'up') {
if (index === 0) return
moveDimension(index, index - 1)
return
}
if (index === dimensions.length - 1) return
moveDimension(index, index + 1)

Copilot uses AI. Check for mistakes.
onOpenChange={() => setVariableFilters((prev) => ({ ...prev, [scope.definition]: '' }))}
>
<PrimitiveDropdown.SubTrigger asChild>
<div className='relative flex h-8 w-full cursor-pointer items-center justify-center py-1 outline-none hover:bg-neutral-100 dark:hover:bg-neutral-900'>
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

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

The className string on this line is duplicated across multiple similar elements in this file (lines 243, 312). Consider extracting this repeated style pattern into a constant or using a shared component to improve maintainability.

Copilot uses AI. Check for mistakes.
- Fix handleRearrangeDimensions to use immutable state updates
  (create copy before using splice instead of mutating state directly)
- Simplify isBaseType check using includes() instead of forEach loop

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
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: 2

🤖 Fix all issues with AI agents
In
@src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx:
- Around line 83-86: handleAddDimension has a stale closure: it uses
dimensions.length (captured) immediately after calling setDimensions, so
selectedInput gets the old index; change handleAddDimension to use the
functional updater form for setDimensions (e.g., setDimensions(prev => { const
newIndex = prev.length; const next = [...prev, ''];
setSelectedInput(newIndex.toString()); return next; })) so selectedInput is
derived from prev.length and matches the newly added dimension.
- Around line 146-160: The code currently sets the inner type definition based
only on baseTypes (isBaseType) which misclassifies function block types; update
the logic where updateVariable is called (the type.data.baseType block using
typeValue and isBaseType) to first check membership in systemFunctionBlocks or
userFunctionBlocks and, if matched, set definition to 'derived', else if
isBaseType set 'base-type', otherwise set 'user-data-type' (preserving value:
typeValue); keep existing surrounding structure (formatArrayName, variableRow,
scope: 'global') unchanged.
🧹 Nitpick comments (1)
src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx (1)

156-160: Consider removing or documenting the @ts-expect-error suppression.

The comment notes "This is being fixed" but doesn't indicate the tracking issue or timeline. If this is a known type mismatch with a planned fix, consider linking to an issue for traceability.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4cf15f4 and 36ec977.

📒 Files selected for processing (1)
  • src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-16T14:31:51.786Z
Learnt from: vmleroy
Repo: Autonomy-Logic/openplc-editor PR: 265
File: src/renderer/components/_atoms/graphical-editor/ladder/block.tsx:149-153
Timestamp: 2025-06-16T14:31:51.786Z
Learning: In src/renderer/components/_atoms/graphical-editor/ladder/block.tsx, the libraries.system data is dynamic and imported from JSON with varying structure, making proper static typing infeasible. The ts-expect-error and eslint-disable comments are justified when dynamically probing the structure at runtime.

Applied to files:

  • src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx
📚 Learning: 2025-07-04T15:13:57.599Z
Learnt from: vmleroy
Repo: Autonomy-Logic/openplc-editor PR: 274
File: src/types/PLC/devices/configuration.ts:0-0
Timestamp: 2025-07-04T15:13:57.599Z
Learning: In src/types/PLC/devices/configuration.ts, the team prefers to handle IP address validation at the local store level when passing values from frontend to backend, rather than adding additional validation at the schema level.

Applied to files:

  • src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: build (windows-latest)
  • GitHub Check: test (windows-latest)
  • GitHub Check: test (macos-latest)
🔇 Additional comments (1)
src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx (1)

20-195: Overall: Well-structured modal component.

The component follows established patterns in the codebase, properly handles store integration, and includes appropriate validation. The dimension manipulation handlers are comprehensive. Based on learnings, the dynamic type handling for libraries data is acceptable given the varying JSON structure.

Comment on lines +83 to +86
const handleAddDimension = () => {
setDimensions((prev) => [...prev, ''])
setSelectedInput(dimensions.length.toString())
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Stale closure bug in handleAddDimension.

dimensions.length captures the value at the time the handler was created, not after the state update. Since setDimensions is asynchronous, selectedInput will be set to the old length rather than the new dimension's index.

🐛 Proposed fix using functional update
 const handleAddDimension = () => {
-  setDimensions((prev) => [...prev, ''])
-  setSelectedInput(dimensions.length.toString())
+  setDimensions((prev) => {
+    setSelectedInput(prev.length.toString())
+    return [...prev, '']
+  })
 }

Alternatively, use a ref or compute the new length explicitly:

 const handleAddDimension = () => {
+  const newIndex = dimensions.length
   setDimensions((prev) => [...prev, ''])
-  setSelectedInput(dimensions.length.toString())
+  setSelectedInput(newIndex.toString())
 }
📝 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 handleAddDimension = () => {
setDimensions((prev) => [...prev, ''])
setSelectedInput(dimensions.length.toString())
}
const handleAddDimension = () => {
const newIndex = dimensions.length
setDimensions((prev) => [...prev, ''])
setSelectedInput(newIndex.toString())
}
🤖 Prompt for AI Agents
In
@src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx
around lines 83 - 86, handleAddDimension has a stale closure: it uses
dimensions.length (captured) immediately after calling setDimensions, so
selectedInput gets the old index; change handleAddDimension to use the
functional updater form for setDimensions (e.g., setDimensions(prev => { const
newIndex = prev.length; const next = [...prev, ''];
setSelectedInput(newIndex.toString()); return next; })) so selectedInput is
derived from prev.length and matches the newly added dimension.

Comment on lines +146 to +160
const isBaseType = baseTypes.includes(typeValue)

updateVariable({
scope: 'global',
rowId: variableRow,
data: {
type: {
definition: 'array',
value: formatArrayName,
data: {
// @ts-expect-error - This is a valid operation. This is being fixed.
baseType: {
definition: isBaseType ? 'base-type' : 'user-data-type',
value: typeValue,
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for baseType definition patterns to understand how function blocks are handled
rg -n "definition.*base-type|definition.*user-data-type|definition.*derived" --type ts -B2 -A2

Repository: Autonomy-Logic/openplc-editor

Length of output: 50386


🏁 Script executed:

# Look for how LibraryTypes or function block types are used in array handling
rg -n "LibraryTypes|userFunctionBlocks|systemFunctionBlocks" --type ts src/renderer/components/_molecules/global-variables-table/ -A3 -B3

Repository: Autonomy-Logic/openplc-editor

Length of output: 6674


🏁 Script executed:

# Find the baseTypes definition to understand what types are considered base types
rg -n "baseTypes|baseTypeSchema" --type ts src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx -B5 -A5

Repository: Autonomy-Logic/openplc-editor

Length of output: 1765


🏁 Script executed:

# Check for array variable type handling in POU context (if it exists)
fd "array" --type f src/renderer/components/_molecules/ | head -20

Repository: Autonomy-Logic/openplc-editor

Length of output: 318


🏁 Script executed:

# Search for how variable types are classified in the broader codebase
rg -n "typeValue.*definition|isBaseType" --type ts -C4

Repository: Autonomy-Logic/openplc-editor

Length of output: 8610


🏁 Script executed:

# Check if there are tests or other usages that show function blocks in arrays
rg -n "derived.*function-block|function-block.*derived" --type ts -B2 -A2 | head -30

Repository: Autonomy-Logic/openplc-editor

Length of output: 55


🏁 Script executed:

# Verify the structure of LibraryTypes selection in array-modal
sed -n '180,220p' src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx

Repository: Autonomy-Logic/openplc-editor

Length of output: 563


Handle function block type classification separately.

The logic classifies typeValue as either 'base-type' or 'user-data-type' based solely on whether it exists in baseTypes. However, function blocks selected from LibraryTypes (which are uppercase) will never match baseTypes (lowercase), causing them to be incorrectly assigned definition: 'user-data-type'.

Function block types should use definition: 'derived' instead. Add a check: if typeValue matches any function block from systemFunctionBlocks or userFunctionBlocks, assign 'derived'. Only unmatched non-base types should fall back to 'user-data-type' (for user-defined structs).

🤖 Prompt for AI Agents
In
@src/renderer/components/_molecules/global-variables-table/elements/array-modal.tsx
around lines 146 - 160, The code currently sets the inner type definition based
only on baseTypes (isBaseType) which misclassifies function block types; update
the logic where updateVariable is called (the type.data.baseType block using
typeValue and isBaseType) to first check membership in systemFunctionBlocks or
userFunctionBlocks and, if matched, set definition to 'derived', else if
isBaseType set 'base-type', otherwise set 'user-data-type' (preserving value:
typeValue); keep existing surrounding structure (formatArrayName, variableRow,
scope: 'global') unchanged.

@thiagoralves thiagoralves merged commit 92dbcf6 into development Jan 10, 2026
8 checks passed
@thiagoralves thiagoralves deleted the fix/global-variables-all-types branch January 10, 2026 04:59
@coderabbitai coderabbitai Bot mentioned this pull request Jan 19, 2026
6 tasks
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