Skip to content

Commit 24c0ff1

Browse files
Copilotaiday-mar
andauthored
Fix hex color detection in strings by adding lookbehind patterns (microsoft#251589)
* Initial plan for issue * Fix hex color detection in strings by adding lookbehind patterns Co-authored-by: aiday-mar <[email protected]> * Simplify hex color detection to only support quotes, remove other delimiters Co-authored-by: aiday-mar <[email protected]> * polish --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: aiday-mar <[email protected]> Co-authored-by: Aiday Marlen Kyzy <[email protected]>
1 parent b2e66f6 commit 24c0ff1

File tree

2 files changed

+103
-1
lines changed

2 files changed

+103
-1
lines changed

src/vs/editor/common/languages/defaultDocumentColorsComputer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function _findMatches(model: IDocumentColorComputerTarget | string, regex: RegEx
101101
function computeColors(model: IDocumentColorComputerTarget): IColorInformation[] {
102102
const result: IColorInformation[] = [];
103103
// Early validation for RGB and HSL
104-
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%]*\))|\s+(#)([A-Fa-f0-9]{6})\b|\s+(#)([A-Fa-f0-9]{8})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b/gm;
104+
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%]*\))|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"\s])(#)([A-Fa-f0-9]{6})\b|(?<=['"\s])(#)([A-Fa-f0-9]{8})\b/gm;
105105
const initialValidationMatches = _findMatches(model, initialValidationRegex);
106106

107107
// Potential colors have been found, validate the parameters
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
import * as assert from 'assert';
6+
import { computeDefaultDocumentColors } from '../../../common/languages/defaultDocumentColorsComputer.js';
7+
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
8+
9+
suite('Default Document Colors Computer', () => {
10+
11+
class TestDocumentModel {
12+
constructor(private content: string) { }
13+
14+
getValue(): string {
15+
return this.content;
16+
}
17+
18+
positionAt(offset: number) {
19+
const lines = this.content.substring(0, offset).split('\n');
20+
return {
21+
lineNumber: lines.length,
22+
column: lines[lines.length - 1].length + 1
23+
};
24+
}
25+
26+
findMatches(regex: RegExp): RegExpMatchArray[] {
27+
return [...this.content.matchAll(regex)];
28+
}
29+
}
30+
31+
ensureNoDisposablesAreLeakedInTestSuite();
32+
33+
test('Hex colors in strings should be detected', () => {
34+
// Test case from issue: hex color inside string is not detected
35+
const model = new TestDocumentModel("const color = '#ff0000';");
36+
const colors = computeDefaultDocumentColors(model);
37+
38+
assert.strictEqual(colors.length, 1, 'Should detect one hex color');
39+
assert.strictEqual(colors[0].color.red, 1, 'Red component should be 1 (255/255)');
40+
assert.strictEqual(colors[0].color.green, 0, 'Green component should be 0');
41+
assert.strictEqual(colors[0].color.blue, 0, 'Blue component should be 0');
42+
assert.strictEqual(colors[0].color.alpha, 1, 'Alpha should be 1');
43+
});
44+
45+
test('Hex colors in double quotes should be detected', () => {
46+
const model = new TestDocumentModel('const color = "#00ff00";');
47+
const colors = computeDefaultDocumentColors(model);
48+
49+
assert.strictEqual(colors.length, 1, 'Should detect one hex color');
50+
assert.strictEqual(colors[0].color.red, 0, 'Red component should be 0');
51+
assert.strictEqual(colors[0].color.green, 1, 'Green component should be 1 (255/255)');
52+
assert.strictEqual(colors[0].color.blue, 0, 'Blue component should be 0');
53+
});
54+
55+
test('Multiple hex colors in array should be detected', () => {
56+
const model = new TestDocumentModel("const colors = ['#ff0000', '#00ff00', '#0000ff'];");
57+
const colors = computeDefaultDocumentColors(model);
58+
59+
assert.strictEqual(colors.length, 3, 'Should detect three hex colors');
60+
61+
// First color: red
62+
assert.strictEqual(colors[0].color.red, 1, 'First color red component should be 1');
63+
assert.strictEqual(colors[0].color.green, 0, 'First color green component should be 0');
64+
assert.strictEqual(colors[0].color.blue, 0, 'First color blue component should be 0');
65+
66+
// Second color: green
67+
assert.strictEqual(colors[1].color.red, 0, 'Second color red component should be 0');
68+
assert.strictEqual(colors[1].color.green, 1, 'Second color green component should be 1');
69+
assert.strictEqual(colors[1].color.blue, 0, 'Second color blue component should be 0');
70+
71+
// Third color: blue
72+
assert.strictEqual(colors[2].color.red, 0, 'Third color red component should be 0');
73+
assert.strictEqual(colors[2].color.green, 0, 'Third color green component should be 0');
74+
assert.strictEqual(colors[2].color.blue, 1, 'Third color blue component should be 1');
75+
});
76+
77+
test('Existing functionality should still work', () => {
78+
// Test cases that were already working
79+
const testCases = [
80+
{ content: "const color = ' #ff0000';", name: 'hex with space before' },
81+
{ content: '#ff0000', name: 'hex at start of line' },
82+
{ content: ' #ff0000', name: 'hex with whitespace before' }
83+
];
84+
85+
testCases.forEach(testCase => {
86+
const model = new TestDocumentModel(testCase.content);
87+
const colors = computeDefaultDocumentColors(model);
88+
assert.strictEqual(colors.length, 1, `Should still detect ${testCase.name}`);
89+
});
90+
});
91+
92+
test('8-digit hex colors should also work', () => {
93+
const model = new TestDocumentModel("const color = '#ff0000ff';");
94+
const colors = computeDefaultDocumentColors(model);
95+
96+
assert.strictEqual(colors.length, 1, 'Should detect one 8-digit hex color');
97+
assert.strictEqual(colors[0].color.red, 1, 'Red component should be 1');
98+
assert.strictEqual(colors[0].color.green, 0, 'Green component should be 0');
99+
assert.strictEqual(colors[0].color.blue, 0, 'Blue component should be 0');
100+
assert.strictEqual(colors[0].color.alpha, 1, 'Alpha should be 1 (ff/255)');
101+
});
102+
});

0 commit comments

Comments
 (0)