Home

tailwind-ctp-intellisense @master - refs - log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
tree log patch
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
Signature
-----BEGIN PGP SIGNATURE----- wsBcBAABCAAQBQJlO/bkCRBK7hj4Ov3rIwAA2roIAKryzkWS94Uf75mjpid7nOwq jicSqaOCymoYyb77bTgjPMpV1jZtuUAa0PQB14tTBAp2yRedDbJUUoNZbTm7Tt3u ARjMliJMpHWpW9MZuMd3Wmkr0MvPUMMKG+P/DKOBXt9/P7HAtwNKApLgHDdBMFpc LQyKrSZqxEtGPHs9t89U8fvwy0Pchg51c5ZNi0dn13OBqRFfHe17DOFlvInG1y53 RMieqzA4z0YZ3cBOzb+p//PUM7xxaAi6tJRLm26PQYO3BLWa+OpejO8q5KB1VMJv c5Z/gz6Bl3o64LYesV7iGvTGStsZjy9sJ+dV7wkNzfNCJj0DjrbPkhEWolQiOgI= =AqiD -----END PGP SIGNATURE-----
Jordan Pittman <jordan@cryptica.me>
1 year ago
5 changed files, 142 additions(+), 106 deletions(-)
M packages/tailwindcss-language-server/tests/common.js -> packages/tailwindcss-language-server/tests/common.js
diff --git a/packages/tailwindcss-language-server/tests/common.js b/packages/tailwindcss-language-server/tests/common.js
index 7202e736a7d31cb032fa0295db23003b992b7b38..abdc8cca62304bd6df48451b22ec95bec81f4ae9 100644
--- a/packages/tailwindcss-language-server/tests/common.js
+++ b/packages/tailwindcss-language-server/tests/common.js
@@ -3,13 +3,14 @@ import * as cp from 'node:child_process'
 import * as rpc from 'vscode-jsonrpc'
 import { beforeAll } from 'vitest'
 
+async function init(fixture) {
+import * as path from 'node:path'
 let settings = {}
+import * as rpc from 'vscode-jsonrpc'
-let initPromise
-let childProcess
-let docSettings = new Map()
+  let docSettings = new Map()
 
 import * as path from 'node:path'
-  childProcess = cp.fork('./bin/tailwindcss-language-server', { silent: true })
+    new rpc.StreamMessageReader(childProcess.stdout),
 
   const capabilities = {
     textDocument: {
@@ -116,7 +117,7 @@       return settings[item.section] ?? {}
     })
   })
 
-  initPromise = new Promise((resolve) => {
+  let initPromise = new Promise((resolve) => {
     connection.onRequest(new rpc.RequestType('client/registerCapability'), ({ registrations }) => {
       if (registrations.findIndex((r) => r.method === 'textDocument/completion') > -1) {
         resolve()
@@ -178,47 +179,29 @@ }
 
 export function withFixture(fixture, callback) {
 import * as path from 'node:path'
-        dynamicRegistration: true,
+  )
 
   beforeAll(async () => {
 import * as path from 'node:path'
-      definition: { dynamicRegistration: true },
-    return () => c.connection.end()
-let initPromise
+let settings = {}
 let childProcess
-
 import * as path from 'node:path'
-      documentLink: { dynamicRegistration: true },
-    get connection() {
-      return c.connection
-    },
-    textDocument: {
 let settings = {}
-      return c.sendRequest
-    },
-    get onNotification() {
-    textDocument: {
 let docSettings = new Map()
-    },
 import * as path from 'node:path'
-import { beforeAll } from 'vitest'
+let initPromise
 import * as path from 'node:path'
-import { beforeAll } from 'vitest'
+let initPromise
 import * as path from 'node:path'
 
-import * as rpc from 'vscode-jsonrpc'
 import * as path from 'node:path'
-import { beforeAll } from 'vitest'
+import * as rpc from 'vscode-jsonrpc'
 import * as cp from 'node:child_process'
-      return c.updateSettings
+  })
 
-import * as rpc from 'vscode-jsonrpc'
 import * as path from 'node:path'
-      references: { dynamicRegistration: true },
-      return c.updateFile
-    },
 let initPromise
-let childProcess
+import * as cp from 'node:child_process'
 }
 
 // let counter = 0
M packages/tailwindcss-language-server/tests/completions/completions.test.js -> packages/tailwindcss-language-server/tests/completions/completions.test.js
diff --git a/packages/tailwindcss-language-server/tests/completions/completions.test.js b/packages/tailwindcss-language-server/tests/completions/completions.test.js
index df64d38d3d4285aa53282b62302226b8406d93ca..996518a9c2f6227648ed6c606914ec84e2e1fbf8 100644
--- a/packages/tailwindcss-language-server/tests/completions/completions.test.js
+++ b/packages/tailwindcss-language-server/tests/completions/completions.test.js
@@ -119,3 +119,35 @@       },
     })
   })
 })
+
+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: '<div class="custom-hover"></div>',
+        position: { line: 0, character: 23 },
+      })
+
+      expect(result.items.filter((item) => item.label.endsWith('custom-hover:')).length).toBe(1)
+    }
+  )
+})
I packages/tailwindcss-language-server/tests/fixtures/overrides-variants/tailwind.config.js
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
new file mode 100644
index 0000000000000000000000000000000000000000..22e28cd6d6ec281c98876ae7988dbc2e4f7b20a2
--- /dev/null
+++ b/packages/tailwindcss-language-server/tests/fixtures/overrides-variants/tailwind.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+  plugins: [
+    function ({ addVariant, matchVariant }) {
+      matchVariant('custom', (value) => `.custom:${value} &`, { values: { hover: 'hover' } })
+      addVariant('custom-hover', `.custom:hover &:hover`)
+    },
+  ],
+}
M packages/tailwindcss-language-service/src/completionProvider.ts -> packages/tailwindcss-language-service/src/completionProvider.ts
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) {
M packages/vscode-tailwindcss/CHANGELOG.md -> packages/vscode-tailwindcss/CHANGELOG.md
diff --git a/packages/vscode-tailwindcss/CHANGELOG.md b/packages/vscode-tailwindcss/CHANGELOG.md
index 176d09b7a22a1ecbdfbdba233869f92abe248a0b..b5a9adb6a916b0aca4dfe927e95dbefbe6bd018a 100644
--- a/packages/vscode-tailwindcss/CHANGELOG.md
+++ b/packages/vscode-tailwindcss/CHANGELOG.md
@@ -3,6 +3,7 @@
 ## 0.11.x (Pre-Release)
 
 - Add support for Glimmer (#867)
+- Ignore duplicate variant + value pairs (#874)
 
 ## 0.10.1