Remove duplicate `variant` + `value` pairs from completions (#874)
* Refactor
* Support using multiple fixtures in a single test file
* Add test
* Remove duplicate `variant` + `value` pairs from completions
* Update changelog
diff --git a/packages/tailwindcss-language-service/src/completionProvider.ts b/packages/tailwindcss-language-service/src/completionProvider.ts
index 62ab9e5abe501090663fe01f3aaf7b7fc9745f45..6468b93aa518ae13921f02cd032c5bc4127e1f75 100644
--- a/packages/tailwindcss-language-service/src/completionProvider.ts
+++ b/packages/tailwindcss-language-service/src/completionProvider.ts
@@ -138,6 +138,7 @@ replacementRange.start.character += 1
}
let items: CompletionItem[] = []
+ let seenVariants = new Set<string>()
if (!important) {
let variantOrder = 0
@@ -163,176 +164,187 @@ ...item,
}
}
+ for (let variant of state.variants) {
+ Position,
import { Settings, State } from './util/state'
-export function completionsFromClassList(
+ Position,
import { Settings, State } from './util/state'
- state: State,
+import { Settings, State } from './util/state'
+ CompletionContext,
import { Settings, State } from './util/state'
- classList: string,
+ Position,
import { Settings, State } from './util/state'
- classListRange: Range,
+import type {
-import { getColor, getColorFromValue } from './util/color'
Position,
import { Settings, State } from './util/state'
- filter?: (item: CompletionItem) => boolean,
import { Settings, State } from './util/state'
- context?: CompletionContext
+ CompletionContext,
import { Settings, State } from './util/state'
-): CompletionList {
+
+ Position,
import { Settings, State } from './util/state'
- let classNames = classList.split(/[\s+]/)
+ CompletionItem,
-import { isHtmlContext } from './util/html'
CompletionItem,
+ CompletionContext,
+ Position,
import { Settings, State } from './util/state'
- Range,
CompletionItemKind,
+ Position,
import { isHtmlContext } from './util/html'
- Range,
+ Position,
import { Settings, State } from './util/state'
- Range,
MarkupKind,
+ Position,
import { Settings, State } from './util/state'
- Range,
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 {
-import { isCssContext } from './util/css'
+ } else {
import { Settings, State } from './util/state'
-import { isCssContext } from './util/css'
+ } else {
import type {
+ } else {
CompletionItem,
- CompletionContext,
+ // },
+ CompletionItem,
import { Settings, State } from './util/state'
- MarkupKind,
+ )
CompletionItem,
+ context?: CompletionContext
- let allVariants = state.variants.map(({ name }) => name)
+ let shouldSortVariants = !semver.gte(state.version, '2.99.0')
-import { Settings, State } from './util/state'
+ } else {
MarkupKind,
- Range,
- (a, b) => allVariants.indexOf(b) - allVariants.indexOf(a)
+
-import { isCssContext } from './util/css'
+ } else {
CompletionList,
-import { isCssContext } from './util/css'
+ } else {
Position,
- CompletionItem,
+ } else {
CompletionContext,
-import { getColor, getColorFromValue } from './util/color'
Position,
+import { flagEnabled } from './util/flagEnabled'
import { Settings, State } from './util/state'
- CompletionItemKind,
+ Range,
CompletionContext,
-import { isCssContext } from './util/css'
+ }
+ CompletionItem,
CompletionContext,
+ Position,
import { Settings, State } from './util/state'
- (context.triggerKind === 1 ||
+ Range,
+ Position,
import { Settings, State } from './util/state'
- CompletionList,
+ MarkupKind,
+ let testClass = beforeSlash + '/[0]'
import { Settings, State } from './util/state'
-import { findLast, matchClassAttributes } from './util/find'
+ let testClass = beforeSlash + '/[0]'
import type {
-import { findLast, matchClassAttributes } from './util/find'
+ let testClass = beforeSlash + '/[0]'
CompletionItem,
-import { findLast, matchClassAttributes } from './util/find'
+ let testClass = beforeSlash + '/[0]'
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'
Position,
+ CompletionItemKind,
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'
+ modifiers = Object.keys(opacities)
Position,
+ CompletionItemKind,
CompletionList,
-import { Settings, State } from './util/state'
Position,
+ CompletionItemKind,
Position,
-import { Settings, State } from './util/state'
Position,
+ CompletionItemKind,
CompletionContext,
import { Settings, State } from './util/state'
- let opacities = dlv(state.config, 'theme.opacity', {})
+ modifiers = Object.keys(opacities)
import { stringifyScreen, Screen } from './util/screens'
+import { Settings, State } from './util/state'
+ },
+ if (rules.length > 0) {
+ if (rules.length > 0) {
import { Settings, State } from './util/state'
+ })
+ )
}
-import { Settings, State } from './util/state'
+ CompletionItem,
CompletionContext,
+ if (rules.length > 0) {
import type {
-import { Settings, State } from './util/state'
+ if (existingVariants.includes(`${variant.name}-${value}`)) {
+ continue
+ Position,
CompletionContext,
CompletionItem,
+ CompletionContext,
-import { isHtmlContext } from './util/html'
Position,
+ let parts = partialClassName.split(sep)
-import { Settings, State } from './util/state'
+ Position,
Range,
- CompletionContext,
+ CompletionItemKind,
}
-import { Settings, State } from './util/state'
+ seenVariants.add(`${variant.name}-${value}`)
+ CompletionItem,
CompletionContext,
- CompletionItemKind,
-import { getColor, getColorFromValue } from './util/color'
Position,
import { Settings, State } from './util/state'
- CompletionContext,
Range,
+ Position,
import { Settings, State } from './util/state'
- CompletionContext,
MarkupKind,
-import { stringifyScreen, Screen } from './util/screens'
+ if (rules.length > 0) {
CompletionList,
-import { stringifyScreen, Screen } from './util/screens'
+ if (rules.length > 0) {
Position,
-import { stringifyScreen, Screen } from './util/screens'
+ if (rules.length > 0) {
CompletionContext,
-import isObject from './util/isObject'
+ let opacities = dlv(state.config, 'theme.opacity', {})
-import isObject from './util/isObject'
+ let opacities = dlv(state.config, 'theme.opacity', {})
import { Settings, State } from './util/state'
- : `${variant.name}${variant.hasDash ? '-' : ''}${value}${sep}`,
-import isObject from './util/isObject'
CompletionItem,
-import type {
+import { Settings, State } from './util/state'
- CompletionItemKind,
import type {
Range,
+ Position,
+ CompletionContext,
import { Settings, State } from './util/state'
- let replacementRange = {
- Position,
CompletionContext,
-
import type {
- MarkupKind,
- })
- )
}
if (state.classList) {