From f5872b398dd3edcdc3e7b41ff1d4cbfdad0e29d4 Mon Sep 17 00:00:00 2001 From: NgoQuocViet2001 Date: Wed, 15 Jul 2026 14:41:07 +0700 Subject: [PATCH] fix: suppress completions inside comments --- src/services/cssCompletion.ts | 36 +++++++++++++++++++++++++++++++++ src/test/css/completion.test.ts | 15 ++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/services/cssCompletion.ts b/src/services/cssCompletion.ts index e8b94a29..7144ec4d 100644 --- a/src/services/cssCompletion.ts +++ b/src/services/cssCompletion.ts @@ -18,6 +18,9 @@ import * as l10n from '@vscode/l10n'; import { isDefined } from '../utils/objects.js'; import { CSSDataManager } from '../languageFacts/dataManager.js'; import { PathCompletionParticipant } from './pathCompletion.js'; +import { Scanner, TokenType } from '../parser/cssScanner.js'; +import { SCSSScanner } from '../parser/scssScanner.js'; +import { LESSScanner } from '../parser/lessScanner.js'; const SnippetFormat = InsertTextFormat.Snippet; @@ -115,6 +118,9 @@ export class CSSCompletion { }, items: [] }; + if (isInsideComment(document, this.offset)) { + return result; + } this.nodePath = nodes.getNodePath(this.styleSheet, this.offset); for (let i = this.nodePath.length - 1; i >= 0; i--) { @@ -1111,6 +1117,36 @@ class Set { } } +function isInsideComment(document: TextDocument, offset: number): boolean { + let scanner: Scanner; + switch (document.languageId) { + case 'scss': + scanner = new SCSSScanner(); + break; + case 'less': + scanner = new LESSScanner(); + break; + default: + scanner = new Scanner(); + } + scanner.ignoreComment = false; + const text = document.getText(); + scanner.setSource(text); + + let token = scanner.scan(); + while (token.type !== TokenType.EOF && token.offset <= offset) { + if (token.type === TokenType.Comment || token.type === TokenType.SingleLineComment) { + const tokenEnd = token.offset + token.len; + const isSingleLineComment = text.startsWith('//', token.offset); + if (offset < tokenEnd || (isSingleLineComment && offset === tokenEnd)) { + return true; + } + } + token = scanner.scan(); + } + return false; +} + function moveCursorInsideParenthesis(text: string): string { return text.replace(/\(\)$/, "($1)"); } diff --git a/src/test/css/completion.test.ts b/src/test/css/completion.test.ts index b0848b65..452bfc82 100644 --- a/src/test/css/completion.test.ts +++ b/src/test/css/completion.test.ts @@ -206,6 +206,21 @@ suite('CSS - Completion', () => { }); }); test('selectors', async function () { + await testCompletionFor('/* comment:| */', { + count: 0 + }); + await testCompletionFor('/* comment */:|', { + items: [ + { label: ':hover' } + ] + }); + await testCompletionFor('// comment:|', { + count: 0 + }, undefined, 'test://test/test.scss'); + await testCompletionFor('// comment:|', { + count: 0 + }, undefined, 'test://test/test.less'); + await testCompletionFor('a:h| ', { items: [ { label: ':hover', resultText: 'a:hover ' },