Skip to content

Fix negation handling in IF function parameters for conditional expressions#585

Draft
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-ppelementdisabled-logic
Draft

Fix negation handling in IF function parameters for conditional expressions#585
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-ppelementdisabled-logic

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Oct 21, 2025

Problem

The Drapo expression parser was incorrectly handling negation (!) when used within function parameters, causing conditional expressions like IF(!ContainsDataItem(...)) to fail. This affected security-related UI components where permissions needed to be checked with negated conditions.

Working patterns:

<!-- Direct negation - worked -->
<input d-class="{switch, disabled:!ContainsDataItem({{userFeatures}},81)}" />

<!-- Negation outside IF - worked -->  
<input d-class="{switch, disabled:!IF(ContainsDataItem({{userFeatures}},81))}" />

Failing pattern:

<!-- Negation inside IF parameter - failed -->
<input d-class="{switch, disabled:IF(!ContainsDataItem({{userFeatures}},81))}" />

Root Cause

The GetFunctionStart method in DrapoParser.ts was incorrectly stripping the ! character from function expressions when they appeared as parameters to other functions. The parsing flow was:

  1. IF(!ContainsDataItem(...)) gets parsed correctly as IF function with parameter !ContainsDataItem(...)
  2. When resolving the parameter, ParseFunctions calls GetFunctionStart on !ContainsDataItem(...)
  3. GetFunctionStart skips the ! character, thinking it's invalid
  4. Result: ContainsDataItem(...) without negation - losing the logical condition

Solution

Modified the function start detection logic to intelligently handle negation:

  • Added ShouldSkipFunctionStartCharacter: Analyzes whether ! should be skipped based on context
  • Smart negation detection: Only skips ! when it's a standalone negation, preserves it when part of valid function parameters
  • Backwards compatible: All existing functionality continues to work

The fix specifically handles cases where ! is followed by a valid function call pattern (e.g., !ContainsDataItem(...)) and preserves the negation in those contexts.

Testing

Added comprehensive test coverage for:

  • IF(!ContainsDataItem(...)) - the main fix
  • !IF(ContainsDataItem(...)) - backwards compatibility verification
  • d-class attribute integration with negated conditions
  • Both positive and negative permission scenarios

Security & Quality

  • CodeQL Security Scan: 0 vulnerabilities found
  • TypeScript Linting: All TSLint checks pass
  • Build Verification: All projects compile successfully
  • Backwards Compatibility: Existing functionality preserved

This fix enables more flexible permission checking patterns in Drapo applications while maintaining full backwards compatibility.

Original prompt

This section details on the original issue you should resolve

<issue_title>failed condition for a ppElementDisabled using ContainsDataItem and more condition</issue_title>
<issue_description>Using the panelSecurityUserNewOrEdit.tml file, I created a new datakey 'panelUserFeatures' containing the user's permissions. The screen already has the parameter 'panelSecurityUserNewOrEditObjectSave.IsBlocked', which identifies whether the user is blocked or not. In the 'Blocked' field, adding a d-class with the following code works. Condition 81 is the 'unblock user' feature.
d-class="{ppSwitch, ppElementDisabled:!ContainsDataItem({{panelUserFeatures}},81)}"

In addition to this condition that checks the feature, it is necessary to check whether the user is blocked and only then disable the field.

But at this point, we have a bug: simply inserting '()' in the above condition generates an error and prevents the screen from opening. Wrapping the above condition in an 'IF' statement keeps it working, but adding the second condition with 'IF' doesn't resolve the check correctly. The negative sign inside the 'IF' generates an error. Trying to use two 'IF' statements generates an error due to the parentheses mentioned at the beginning.

It works.
d-class="{ppSwitch, ppElementDisabled:!IF(ContainsDataItem({{panelUserFeatures}},81))}"

It generates an error and doesn't display the screen.
d-class="{ppSwitch, ppElementDisabled:IF(!ContainsDataItem({{panelUserFeatures}},81))}"

And adding the second required part either doesn't respect the condition or generates an error and doesn't display the screen.

Testing rerun on version 12.0

When testing on master, the feature query isn't executed using the same implementation as 12.0, as follows.

Image

Image</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #584


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…sDataItem(...))

Co-authored-by: silvath <2657156+silvath@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix failed condition for ppElementDisabled in user permissions Fix negation handling in IF function parameters for conditional expressions Oct 21, 2025
Copilot AI requested a review from silvath October 21, 2025 14:11
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.

failed condition for a ppElementDisabled using ContainsDataItem and more condition

2 participants