Skip to content

feat(lint): add noReactNativeLiteralColors#10012

Merged
ematipico merged 3 commits intomainfrom
feat/no-literal-color
Apr 18, 2026
Merged

feat(lint): add noReactNativeLiteralColors#10012
ematipico merged 3 commits intomainfrom
feat/no-literal-color

Conversation

@ematipico
Copy link
Copy Markdown
Member

@ematipico ematipico commented Apr 17, 2026

Summary

This PR adds the new nursery rule noReactNativeLiteralColors to the react native domain. Here's the docs of the original rule https://github.com/Intellicode/eslint-plugin-react-native/blob/master/docs/rules/no-color-literals.md

I used a coding agent, but then I changed the rule's logic. Tests have been added by the coding agent.

Test Plan

Added new tests

Docs

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 17, 2026

🦋 Changeset detected

Latest commit: 230566b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ematipico ematipico requested review from a team April 17, 2026 07:40
@github-actions github-actions bot added A-Project Area: project A-Linter Area: linter A-Parser Area: parser L-JavaScript Language: JavaScript and super languages A-Diagnostic Area: diagnostocis labels Apr 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Parser conformance results on

js/262

Test result main count This PR count Difference
Total 53181 53181 0
Passed 51961 51961 0
Failed 1178 1178 0
Panics 42 42 0
Coverage 97.71% 97.71% 0.00%

jsx/babel

Test result main count This PR count Difference
Total 38 38 0
Passed 37 37 0
Failed 1 1 0
Panics 0 0 0
Coverage 97.37% 97.37% 0.00%

markdown/commonmark

Test result main count This PR count Difference
Total 652 652 0
Passed 652 652 0
Failed 0 0 0
Panics 0 0 0
Coverage 100.00% 100.00% 0.00%

symbols/microsoft

Test result main count This PR count Difference
Total 5467 5467 0
Passed 1915 1915 0
Failed 3552 3552 0
Panics 0 0 0
Coverage 35.03% 35.03% 0.00%

ts/babel

Test result main count This PR count Difference
Total 640 640 0
Passed 569 569 0
Failed 71 71 0
Panics 0 0 0
Coverage 88.91% 88.91% 0.00%

ts/microsoft

Test result main count This PR count Difference
Total 18876 18876 0
Passed 13014 13014 0
Failed 5861 5861 0
Panics 1 1 0
Coverage 68.94% 68.94% 0.00%

@Netail Netail changed the title feat(lint): add noReactNativeRawText feat(lint): add noReactNativeLiteralColors Apr 17, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 17, 2026

Walkthrough

Adds a new JavaScript React Native lint rule noReactNativeLiteralColors that flags string literal color values used in style properties whose names include color. The rule checks JSX attributes with names containing style and StyleSheet.create(...) calls (validated against react-native/react-native-web imports), detects string literals and ternary branches that are string literals, and emits diagnostics with notes. Includes tests, rule options, a public AnyStyleSink node union, and an is_string_literal helper on AnyJsExpression.

Suggested reviewers

  • dyc3
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and concisely describes the main change: adding a new lint rule noReactNativeLiteralColors to the linter.
Description check ✅ Passed The description explains the PR's purpose, references the original rule documentation, discloses AI assistance, and outlines the test plan—all related to the changeset.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/no-literal-color

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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_js_analyze/src/lint/nursery/no_react_native_literal_colors.rs`:
- Around line 63-67: The rule declaration for NoReactNativeLiteralColors uses
RuleSource::EslintReactNative("no-color-literals").same(), but since the ported
logic diverged from the original ESLint rule you should call .inspired() instead
of .same(); update the source expression for NoReactNativeLiteralColors (the
RuleSource::EslintReactNative(...) chain) to use .inspired() so the metadata
correctly reflects that this rule is only inspired by the upstream rule.
- Around line 148-164: The function has_color_literal_value currently misses
parenthesized string literals (e.g.,
AnyJsExpression::AnyJsParenthesizedExpression wrapping a
JsStringLiteralExpression), so update has_color_literal_value to treat
parenthesized string literals as color literals: either add pattern arms to
match AnyJsParenthesizedExpression and check its inner expression for
is_string_literal (or recursively unwrap parentheses until a non-parenthesized
node is reached), and apply the same handling for conditional branches
(consequent/alternate) so parenthesised string literals are recognized the same
as bare string literals; reference function has_color_literal_value and the
is_string_literal checks in the conditional branch when making the change.
- Around line 175-190: The is_stylesheet_create function is passing
Some("StyleSheet") to is_framework_api_reference which treats unresolved
identifiers named StyleSheet as matching the React Native API; update the call
in is_stylesheet_create (the function handling JsCallExpression checks) to pass
None instead of Some("StyleSheet") so only actual imports from
REACT_NATIVE_PACKAGE_NAMES are accepted and unresolved/local StyleSheet
identifiers are not flagged.

In `@crates/biome_js_syntax/src/expr_ext.rs`:
- Around line 1371-1375: The is_string_literal helper currently only matches
direct string literal nodes (function is_string_literal) so parenthesised forms
like ('#fff') are missed; update is_string_literal to unwrap
AnyJsParenthesizedExpression (or recursively strip parenthesis wrappers) and
then test the inner expression for
AnyJsLiteralExpression::JsStringLiteralExpression so both direct and
parenthesised string literals return true (either add a loop that peels
Self::AnyJsParenthesizedExpression to its inner expression before matching, or
make the match accept the parenthesized variant that contains a string literal).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 709ecf95-7ffd-43e7-b132-281654214854

📥 Commits

Reviewing files that changed from the base of the PR and between 131019e and c0e446d.

⛔ Files ignored due to path filters (10)
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/domain_selector.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_configuration/src/generated/linter_options_check.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/invalid.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/invalidReactNativeImport.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/valid.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/validCustomStyleSheet.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/validLocalStyleSheet.jsx.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (10)
  • .changeset/no-react-native-literal-colors.md
  • crates/biome_js_analyze/src/lint/nursery/no_react_native_literal_colors.rs
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/invalid.jsx
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/invalidReactNativeImport.jsx
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/valid.jsx
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/validCustomStyleSheet.jsx
  • crates/biome_js_analyze/tests/specs/nursery/noReactNativeLiteralColors/validLocalStyleSheet.jsx
  • crates/biome_js_syntax/src/expr_ext.rs
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_react_native_literal_colors.rs

Comment thread crates/biome_js_syntax/src/expr_ext.rs
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 17, 2026

Merging this PR will not alter performance

✅ 59 untouched benchmarks
⏩ 195 skipped benchmarks1


Comparing feat/no-literal-color (230566b) with main (131019e)

Open in CodSpeed

Footnotes

  1. 195 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions github-actions bot added the A-CLI Area: CLI label Apr 17, 2026
Comment thread crates/biome_js_analyze/src/lint/nursery/no_react_native_literal_colors.rs Outdated
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.

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/no_react_native_literal_colors.rs (1)

148-165: Nested ternaries partially detected.

For deeply nested conditionals like flag ? (flag2 ? '#fff' : '#000') : theme.color, only the outer branches are checked. The inner string literals would slip through. This is likely acceptable for a nursery rule — just flagging it for awareness.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_js_analyze/src/lint/nursery/no_react_native_literal_colors.rs`
around lines 148 - 165, The function has_color_literal_value only checks the
immediate consequent/alternate of a JsConditionalExpression, so nested ternaries
like flag ? (flag2 ? '#fff' : '#000') : theme.color escape detection; update
has_color_literal_value to recursively inspect conditional branches by calling
itself on consequent() and alternate() (and also treat JsStringLiteralExpression
as before) so any depth of nested AnyJsConditionalExpression nested inside
AnyJsExpression is checked for string literal color values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/biome_js_analyze/src/lint/nursery/no_react_native_literal_colors.rs`:
- Around line 148-165: The function has_color_literal_value only checks the
immediate consequent/alternate of a JsConditionalExpression, so nested ternaries
like flag ? (flag2 ? '#fff' : '#000') : theme.color escape detection; update
has_color_literal_value to recursively inspect conditional branches by calling
itself on consequent() and alternate() (and also treat JsStringLiteralExpression
as before) so any depth of nested AnyJsConditionalExpression nested inside
AnyJsExpression is checked for string literal color values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 87c09093-10c2-4533-91d5-064e17507038

📥 Commits

Reviewing files that changed from the base of the PR and between c0e446d and 230566b.

⛔ Files ignored due to path filters (3)
  • crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs is excluded by !**/migrate/eslint_any_rule_to_biome.rs and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (2)
  • crates/biome_js_analyze/src/lint/nursery/no_react_native_literal_colors.rs
  • crates/biome_string_case/src/lib.rs

@ematipico ematipico merged commit 94ccca9 into main Apr 18, 2026
32 checks passed
@ematipico ematipico deleted the feat/no-literal-color branch April 18, 2026 15:20
@github-actions github-actions bot mentioned this pull request Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI A-Diagnostic Area: diagnostocis A-Linter Area: linter A-Parser Area: parser A-Project Area: project L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants