diff --git a/packages/tailwindcss-language-server/tests/common.js b/packages/tailwindcss-language-server/tests/common.js index abdc8cca62304bd6df48451b22ec95bec81f4ae9..7202e736a7d31cb032fa0295db23003b992b7b38 100644 --- a/packages/tailwindcss-language-server/tests/common.js +++ b/packages/tailwindcss-language-server/tests/common.js @@ -3,11 +3,13 @@ import * as cp from 'node:child_process' import * as rpc from 'vscode-jsonrpc' import { beforeAll } from 'vitest' -async function init(fixture) { +let settings = {} - let settings = {} +let initPromise - let docSettings = new Map() +let childProcess +let docSettings = new Map() - let childProcess = cp.fork('./bin/tailwindcss-language-server', { silent: true }) +async function init(fixture) { + childProcess = cp.fork('./bin/tailwindcss-language-server', { silent: true }) const capabilities = { textDocument: { @@ -114,8 +116,9 @@ return settings[item.section] ?? {} }) }) - let docSettings = new Map() +import * as path from 'node:path' + let settings = {} connection.onRequest(new rpc.RequestType('client/registerCapability'), ({ registrations }) => { if (registrations.findIndex((r) => r.method === 'textDocument/completion') > -1) { resolve() @@ -177,28 +180,48 @@ } export function withFixture(fixture, callback) { import * as path from 'node:path' - dynamicRegistration: true, + symbol: { beforeAll(async () => { import * as path from 'node:path' -import * as cp from 'node:child_process' + let childProcess = cp.fork('./bin/tailwindcss-language-server', { silent: true }) codeLens: { dynamicRegistration: true }, +import * as rpc from 'vscode-jsonrpc' + }) + + completionItem: { import * as path from 'node:path' -import * as rpc from 'vscode-jsonrpc' +async function init(fixture) { import * as path from 'node:path' import * as path from 'node:path' -import * as rpc from 'vscode-jsonrpc' +async function init(fixture) { import * as cp from 'node:child_process' +import * as path from 'node:path' import * as path from 'node:path' -import * as rpc from 'vscode-jsonrpc' +async function init(fixture) { import * as rpc from 'vscode-jsonrpc' + return c.sendRequest + }, + get onNotification() { + return c.onNotification + }, + completionItem: { let settings = {} +import * as path from 'node:path' async function init(fixture) { + let docSettings = new Map() +import * as path from 'node:path' import * as path from 'node:path' - 25, 26, + // rootPath: '.', + return c.updateSettings + }, + get updateFile() { + return c.updateFile + }, + }) } // let counter = 0 diff --git a/packages/tailwindcss-language-server/tests/completions/completions.test.js b/packages/tailwindcss-language-server/tests/completions/completions.test.js index 996518a9c2f6227648ed6c606914ec84e2e1fbf8..df64d38d3d4285aa53282b62302226b8406d93ca 100644 --- a/packages/tailwindcss-language-server/tests/completions/completions.test.js +++ b/packages/tailwindcss-language-server/tests/completions/completions.test.js @@ -119,35 +119,3 @@ }, }) }) }) - -withFixture('overrides-variants', (c) => { - async function completion({ - lang, - text, - position, - context = { - triggerKind: 1, - }, - settings, - }) { - let textDocument = await c.openDocument({ text, lang, settings }) - - return c.sendRequest('textDocument/completion', { - textDocument, - position, - context, - }) - } - - test.concurrent( - 'duplicate variant + value pairs do not produce multiple completions', - async () => { - let result = await completion({ - text: '
', - position: { line: 0, character: 23 }, - }) - - expect(result.items.filter((item) => item.label.endsWith('custom-hover:')).length).toBe(1) - } - ) -}) diff --git a/packages/tailwindcss-language-server/tests/fixtures/overrides-variants/tailwind.config.js b/packages/tailwindcss-language-server/tests/fixtures/overrides-variants/tailwind.config.js deleted file mode 100644 index 22e28cd6d6ec281c98876ae7988dbc2e4f7b20a2..0000000000000000000000000000000000000000 --- a/packages/tailwindcss-language-server/tests/fixtures/overrides-variants/tailwind.config.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - plugins: [ - function ({ addVariant, matchVariant }) { - matchVariant('custom', (value) => `.custom:${value} &`, { values: { hover: 'hover' } }) - addVariant('custom-hover', `.custom:hover &:hover`) - }, - ], -} diff --git a/packages/tailwindcss-language-service/src/completionProvider.ts b/packages/tailwindcss-language-service/src/completionProvider.ts index 6468b93aa518ae13921f02cd032c5bc4127e1f75..62ab9e5abe501090663fe01f3aaf7b7fc9745f45 100644 --- a/packages/tailwindcss-language-service/src/completionProvider.ts +++ b/packages/tailwindcss-language-service/src/completionProvider.ts @@ -138,7 +138,6 @@ replacementRange.start.character += 1 } let items: CompletionItem[] = [] - let seenVariants = new Set() if (!important) { let variantOrder = 0 @@ -164,179 +163,169 @@ ...item, } } -import { Settings, State } from './util/state' + (cls) => Array.isArray(cls) && cls[0] === baseClassName CompletionItemKind, + (cls) => Array.isArray(cls) && cls[0] === baseClassName Range, -import { getColor, getColorFromValue } from './util/color' + (cls) => Array.isArray(cls) && cls[0] === baseClassName MarkupKind, - continue - } -import { getColor, getColorFromValue } from './util/color' Position, -import { getColor, getColorFromValue } from './util/color' CompletionList, - } - + items.push( - seenVariants.add(variant.name) - CompletionItem, + (cls) => Array.isArray(cls) && cls[0] === baseClassName CompletionContext, + Position, import { Settings, State } from './util/state' - Range, + Position, import { Settings, State } from './util/state' - Range, import { Settings, State } from './util/state' + Position, import { Settings, State } from './util/state' - Range, import type { + Position, import { Settings, State } from './util/state' - Range, CompletionItem, + Position, import { Settings, State } from './util/state' - Range, CompletionItemKind, + Position, import { Settings, State } from './util/state' - Range, Range, + Position, import { Settings, State } from './util/state' - Range, MarkupKind, + Position, import { Settings, State } from './util/state' - Range, + CompletionList, + }) +import { Settings, State } from './util/state' CompletionList, + Position, import { Settings, State } from './util/state' - Range, Position, + Position, import { Settings, State } from './util/state' - Range, CompletionContext, -import { isCssContext } from './util/css' + } else { - }) + + } else { import { Settings, State } from './util/state' - MarkupKind, + } else { import type { -import { isCssContext } from './util/css' + } else { CompletionItem, -import { isCssContext } from './util/css' + } else { CompletionItemKind, -import { isCssContext } from './util/css' + ) +import type { Range, + CompletionContext, - if (shouldSortVariants) { + items.push( - let allVariants = state.variants.map(({ name }) => name) + variantItem({ -import { isCssContext } from './util/css' Position, -import { Settings, State } from './util/state' +import type { MarkupKind, - CompletionContext, -import { Settings, State } from './util/state' + } else { CompletionList, + .selectors() Position, +import type { CompletionContext, + Position, CompletionItem, - CompletionContext, -import { isHtmlContext } from './util/html' + let testClass = beforeSlash + '/[0]' import { Settings, State } from './util/state' -import { isHtmlContext } from './util/html' + let testClass = beforeSlash + '/[0]' import type { - label: `${variant.name}${sep}`, + shouldSortVariants && resultingVariants.length > 1 - detail: variant -import { findLast, matchClassAttributes } from './util/find' + Position, CompletionItem, -import { findLast, matchClassAttributes } from './util/find' CompletionItemKind, -import { findLast, matchClassAttributes } from './util/find' + let testClass = beforeSlash + '/[0]' Range, -import { findLast, matchClassAttributes } from './util/find' + let testClass = beforeSlash + '/[0]' MarkupKind, -import { findLast, matchClassAttributes } from './util/find' + let testClass = beforeSlash + '/[0]' CompletionList, -import { findLast, matchClassAttributes } from './util/find' + let testClass = beforeSlash + '/[0]' Position, -import { findLast, matchClassAttributes } from './util/find' + let testClass = beforeSlash + '/[0]' CompletionContext, -import { Settings, State } from './util/state' Position, + CompletionItemKind, -import { Settings, State } from './util/state' Position, + CompletionItemKind, import { Settings, State } from './util/state' -import { Settings, State } from './util/state' Position, + CompletionItemKind, import type { -import { Settings, State } from './util/state' Position, + CompletionItemKind, CompletionItem, -import { Settings, State } from './util/state' let { rules } = jit.generateRules(state, [testClass]) + CompletionItemKind, -import { Settings, State } from './util/state' Position, + CompletionItemKind, Range, -import { Settings, State } from './util/state' Position, + CompletionItemKind, MarkupKind, -import { Settings, State } from './util/state' Position, - CompletionList, + : className.__info.__source === 'utilities' import { stringifyConfigValue, stringifyCss } from './util/stringify' - Position, + CompletionList, import { Settings, State } from './util/state' - Position, CompletionContext, import { Settings, State } from './util/state' - modifiers = Object.keys(opacities) -import { Settings, State } from './util/state' Position, + CompletionItemKind, CompletionList, - }, + : [], -import { stringifyScreen, Screen } from './util/screens' +import type { import type { import { Settings, State } from './util/state' + (context.triggerKind === 1 || + Position, CompletionContext, CompletionItem, + CompletionContext, -import { stringifyScreen, Screen } from './util/screens' + Position, CompletionItemKind, + CompletionContext, - }) + items.push( - ) + ...variant.values - CompletionContext, + if (rules.length > 0) { import { Settings, State } from './util/state' + .map((value) => + if (rules.length > 0) { CompletionItem, - CompletionContext, -import { stringifyScreen, Screen } from './util/screens' + Position, Range, + CompletionItemKind, -import { stringifyScreen, Screen } from './util/screens' + value === 'DEFAULT' + if (rules.length > 0) { MarkupKind, -import { stringifyScreen, Screen } from './util/screens' + if (rules.length > 0) { CompletionList, Position, - CompletionContext, + let isSubset: boolean = false - CompletionItem, + if (rules.length > 0) { CompletionContext, -import { stringifyScreen, Screen } from './util/screens' Position, + ...classListRange, import { Settings, State } from './util/state' - CompletionContext, CompletionList, } + let opacities = dlv(state.config, 'theme.opacity', {}) import { Settings, State } from './util/state' - let kind: CompletionItemKind = 21 CompletionItem, - CompletionContext, - items.push( - variantItem({ -import type { import type { -import { Settings, State } from './util/state' import type { -import type { import type { - CompletionItem, - detail: variant.selectors({ value }).join(', '), - }) - ) CompletionContext, -import { Settings, State } from './util/state' - } } if (state.classList) { diff --git a/packages/vscode-tailwindcss/CHANGELOG.md b/packages/vscode-tailwindcss/CHANGELOG.md index b5a9adb6a916b0aca4dfe927e95dbefbe6bd018a..176d09b7a22a1ecbdfbdba233869f92abe248a0b 100644 --- a/packages/vscode-tailwindcss/CHANGELOG.md +++ b/packages/vscode-tailwindcss/CHANGELOG.md @@ -3,7 +3,6 @@ ## 0.11.x (Pre-Release) - Add support for Glimmer (#867) -- Ignore duplicate variant + value pairs (#874) ## 0.10.1