Skip to content

Fix #297799: color picker in private fields#307902

Open
martacbraga wants to merge 1 commit intomicrosoft:mainfrom
martacbraga:martacbraga/color-picker-private-fields
Open

Fix #297799: color picker in private fields#307902
martacbraga wants to merge 1 commit intomicrosoft:mainfrom
martacbraga:martacbraga/color-picker-private-fields

Conversation

@martacbraga
Copy link
Copy Markdown

Fix false positives in default color detection regex

Fixes #297799

This PR updates the default color detection regex to avoid incorrectly matching JavaScript/TypeScript private fields (e.g., #foo) as hex colors.

The default color provider applies to all languages, which caused incorrect matches in JS/TS. Since short hex colors like #fff are mainly relevant for CSS (which has its own color picker), removing this behavior improves accuracy without affecting common use cases like "#000000" in strings.

Changes

  • Prevent matching hex patterns outside strings
  • Avoid false positives for private fields
  • Remove outdated unit test for hex outside strings ({ content: ' #ff0000', name: 'hex with whitespace before' })

How to test

  • #foo → not detected
  • "#000000" → detected

Update regex to avoid matching hex colors outside strings.
Prevent false positives for private fields (#foo).
Preserve valid cases like "#fff".
Copilot AI review requested due to automatic review settings April 5, 2026 15:05
@martacbraga
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copy link
Copy Markdown
Contributor

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 adjusts the editor’s default document color detection to avoid false positives where JavaScript/TypeScript private fields (e.g. #facade) were being detected as hex colors, and updates the associated unit tests.

Changes:

  • Tighten the early-validation regex for hex colors to reduce matches outside quoted strings.
  • Remove an outdated test that asserted hex detection after leading whitespace.
  • Add regression coverage for JS/TS private fields that resemble hex colors.

Reviewed changes

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

File Description
src/vs/editor/common/languages/defaultDocumentColorsComputer.ts Updates the initial color-detection regex to avoid matching #... in more non-string contexts.
src/vs/editor/test/common/languages/defaultDocumentColorsComputer.test.ts Updates tests to reflect the new matching behavior and adds a regression test for private fields.

Comment on lines 103 to 105
// Early validation for RGB and HSL (including CSS Level 4 syntax with / separator)
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%\/]*\))|^(#)([A-Fa-f0-9]{3})\b|^(#)([A-Fa-f0-9]{4})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"\s])(#)([A-Fa-f0-9]{3})\b|(?<=['"\s])(#)([A-Fa-f0-9]{4})\b|(?<=['"\s])(#)([A-Fa-f0-9]{6})\b|(?<=['"\s])(#)([A-Fa-f0-9]{8})\b/gm;
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%\/]*\))|^(#)([A-Fa-f0-9]{3})\b|^(#)([A-Fa-f0-9]{4})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{3})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{4})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{6})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{8})\b/gm;
const initialValidationMatches = _findMatches(model, initialValidationRegex);
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

The new lookbehind (?<=['"][ ]*) is variable-length because of *, which is not supported by the JS RegExp engine and will throw a SyntaxError when this module is parsed. Please rewrite this part of the regex without variable-length lookbehind (e.g. match the quote/whitespace in the overall match and adjust the computed range accordingly, or use only fixed-length lookbehinds).

Copilot uses AI. Check for mistakes.
const result: IColorInformation[] = [];
// Early validation for RGB and HSL (including CSS Level 4 syntax with / separator)
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%\/]*\))|^(#)([A-Fa-f0-9]{3})\b|^(#)([A-Fa-f0-9]{4})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"\s])(#)([A-Fa-f0-9]{3})\b|(?<=['"\s])(#)([A-Fa-f0-9]{4})\b|(?<=['"\s])(#)([A-Fa-f0-9]{6})\b|(?<=['"\s])(#)([A-Fa-f0-9]{8})\b/gm;
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%\/]*\))|^(#)([A-Fa-f0-9]{3})\b|^(#)([A-Fa-f0-9]{4})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{3})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{4})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{6})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{8})\b/gm;
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

This regex still matches bare hex colors at the start of a line via the ^(#)([A-Fa-f0-9]{...}) alternatives. That means a private field written without indentation (e.g. class Foo {\n#facade;\n}) would still be detected as a color, so the false positive isn’t fully eliminated. Consider removing the start-of-line hex alternatives (to align with the PR description of only matching inside strings), or otherwise tightening the non-string matching so it can’t match valid private field syntax.

Suggested change
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%\/]*\))|^(#)([A-Fa-f0-9]{3})\b|^(#)([A-Fa-f0-9]{4})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{3})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{4})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{6})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{8})\b/gm;
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%\/]*\))|(?<=['"][ ]*)(#)([A-Fa-f0-9]{3})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{4})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{6})\b|(?<=['"][ ]*)(#)([A-Fa-f0-9]{8})\b/gm;

Copilot uses AI. Check for mistakes.
// Test case from issue #297799
const testCases = [
{ content: 'class Foo {\n\t#facade\n}', name: 'private field #facade should not be a color' },
{ content: 'class Component {\n\treadonly #facade = inject(Facade);\n}', name: 'private field #facade with injection should not be a color' },
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

The added regression test only covers a 6-hex-digit private field name (#facade). Since the matcher has separate branches for 3/4/6/8-digit hex, it would be good to add a couple of additional cases (e.g. #fed, #fedc, #fedbca0/#fedbcaff) and also a no-indentation variant to ensure private fields aren’t detected regardless of formatting.

Suggested change
{ content: 'class Component {\n\treadonly #facade = inject(Facade);\n}', name: 'private field #facade with injection should not be a color' },
{ content: 'class Component {\n\treadonly #facade = inject(Facade);\n}', name: 'private field #facade with injection should not be a color' },
{ content: 'class Foo {\n\t#fed\n}', name: 'private field #fed should not be a color' },
{ content: 'class Foo {\n\t#fedc\n}', name: 'private field #fedc should not be a color' },
{ content: 'class Foo {\n\t#fedbca0\n}', name: 'private field #fedbca0 should not be a color' },
{ content: 'class Foo {\n\t#fedbcaff\n}', name: 'private field #fedbcaff should not be a color' },
{ content: 'class Foo {\n#fed\n}', name: 'private field #fed without indentation should not be a color' },

Copilot uses AI. Check for mistakes.
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.

Color picker wrongfully appear when declaring private ES6 field

3 participants