Skip to content

Fix not keyword silently ignored when used without parentheses in conditions#4421

Merged
matthew-dean merged 5 commits intomasterfrom
copilot/fix-not-keyword-parenthesis-issue
Mar 19, 2026
Merged

Fix not keyword silently ignored when used without parentheses in conditions#4421
matthew-dean merged 5 commits intomasterfrom
copilot/fix-not-keyword-parenthesis-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 10, 2026

not false and not (false) produced inconsistent results — the parenthesized form correctly negated, while the bare form silently dropped the not entirely.

Root cause: negatedCondition in the parser consumed the not token then only attempted parenthesisCondition. On failure (no (), it returned undefined with not already consumed, causing the caller to parse the bare value without negation.

Fix:

  • parser.js — In negatedCondition, when parenthesisCondition fails, fall back to parsing a simple bare value (keyword, variable, quoted string) without parens. Complex conditions (comparisons, function calls) still require parentheses, aligning with CSS media query syntax:
:root {
  --foo: boolean(not false);    /* was: false — now: true */
  --bar: boolean(not (false));  /* was: true  — still: true */
}

Also works consistently in if() and mixin guards:

.mixin(@a) when not @a { ... }   /* now works, same as: when not (@a) */

Comparisons without parentheses are intentionally not supported — use not (2 < 1) instead of not 2 < 1.

Tests:

  • functions.less/css — added boolean(not false), boolean(not true), if(not false, ...), if(not true, ...)
  • mixins-guards.less/css — added when not @a guard without parentheses
Original prompt

This section details on the original issue you should resolve

<issue_title>Inconsistency with not keyword and parenthesis</issue_title>
<issue_description>To reproduce:

(playground)

:root {
  --foo: boolean(not false); // false
  --bar: boolean(not (false)); // true
}

Current behavior:

I'm guessing this stems from the origins of not as used in when guard expressions, but currently the not keyword only works if the boolean that follows is in parenthesis. If not, it silently does nothing.

Expected behavior:

I would hope that not could be made to work without requiring the parenthesis, if not I would like to perhaps get an error in the case where the not keyword isn't valid / doesn't apply.

Environment information:

  • less version: latest
  • nodejs version: n/a
  • operating system: n/a

</issue_description>

<agent_instructions>Both of these forms should work, but I think this may be a parsing issue where we expect parens after not... ? But if we require it, then we should throw a parsing error, we shouldn't have it both ways.</agent_instructions>

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


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Previously, `boolean(not false)` silently ignored the `not` keyword
while `boolean(not (false))` worked correctly.

The `negatedCondition` parser function consumed the `not` keyword but
only tried `parenthesisCondition`, which requires `(`. With no parens,
it returned undefined with `not` already consumed, causing silent skip.

Fix: fall back to `atomicCondition` when `parenthesisCondition` fails,
allowing both `not false` and `not (false)` to work consistently.

Co-authored-by: matthew-dean <414752+matthew-dean@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix inconsistency with not keyword and parenthesis Fix not keyword silently ignored when used without parentheses in conditions Mar 10, 2026
@matthew-dean
Copy link
Copy Markdown
Member

@copilot Do we not / should we not require parentheses after not() though? It's supposed to align with the media syntax, so shouldn't something like not 2 < 1 trigger a parser error? I feel like it should maybe?

Complex conditions like `not 2 < 1` still require parentheses,
keeping alignment with CSS media query syntax. Only simple bare
values (keywords, variables, quoted strings) are allowed after
`not` without parens: `not false`, `not @var`.

Remove the `boolean(not 2 < 1)` test case that relied on the
broader atomicCondition fallback.

Co-authored-by: matthew-dean <414752+matthew-dean@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 12, 2026

@copilot Do we not / should we not require parentheses after not() though? It's supposed to align with the media syntax, so shouldn't something like not 2 < 1 trigger a parser erro...

Good point. I've updated the fix (571365f → latest) to restrict bare not to simple values only (keywords, variables, quoted strings). Complex conditions like not 2 < 1 still require parentheses, keeping alignment with CSS media syntax:

  • not false ✅ works (simple keyword)
  • not @var ✅ works (variable)
  • not (2 < 1) ✅ works (parenthesized)
  • not 2 < 1 ❌ requires parens — falls back to old parse (the not is effectively dropped)

The fallback in negatedCondition now uses entities.keyword() || entities.variable() || entities.quoted() || entities.mixinLookup() instead of the full atomicCondition, so comparison expressions without parens won't be accepted.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 17, 2026

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 17af5c89-799f-4aae-a185-b63e5ea5166b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch copilot/fix-not-keyword-parenthesis-issue
📝 Coding Plan
  • Generate coding plan for human review comments

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

Tip

CodeRabbit can use your project's `biome` configuration to improve the quality of JS/TS/CSS/JSON code reviews.

Add a configuration file to your project to customize how CodeRabbit runs biome.

@matthew-dean matthew-dean marked this pull request as ready for review March 19, 2026 22:43
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Mar 19, 2026
@matthew-dean matthew-dean merged commit d250d62 into master Mar 19, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inconsistency with not keyword and parenthesis

2 participants