Skip to content

Commit 20890ea

Browse files
Discard function matches that appear after the current cursor in completions (#1278)
Look, it's not a fancy shiny new feature without a bug 😅 When we discover function matches via `tailwindCSS.classFunctions` we were implicitly breaking some assumptions used by the completions code: - No matches for class attributes or functions that appear _after_ the cursor position are found (we weren't discarding these function matches but we need to) - The *last* match is always the one that corresponds to the current cursor position (we collect function matches separately so the order was wrong) This PR fixes this by doing two things: - Discarding function matches that appear after the current cursor position - Sorting the list of attribute and function matches so the last one in the list is always the latest one in the document (up to the cursor)
1 parent 43f9000 commit 20890ea

File tree

3 files changed

+68
-5
lines changed

3 files changed

+68
-5
lines changed

packages/tailwindcss-language-server/tests/completions/completions.test.js

+58
Original file line numberDiff line numberDiff line change
@@ -849,3 +849,61 @@ defineTest({
849849
})
850850
},
851851
})
852+
853+
defineTest({
854+
name: 'v4: class function completions mixed with class attribute completions work',
855+
fs: {
856+
'app.css': css`
857+
@import 'tailwindcss';
858+
`,
859+
},
860+
prepare: async ({ root }) => ({ client: await createClient({ root }) }),
861+
handle: async ({ client }) => {
862+
let document = await client.open({
863+
settings: {
864+
tailwindCSS: {
865+
classAttributes: ['className'],
866+
classFunctions: ['cn', 'cva'],
867+
},
868+
},
869+
lang: 'javascriptreact',
870+
text: js`
871+
let x = cva("")
872+
873+
export function Button() {
874+
return <Test className={cn("")} />
875+
}
876+
877+
export function Button2() {
878+
return <Test className={cn("")} />
879+
}
880+
881+
let y = cva("")
882+
`,
883+
})
884+
885+
// let x = cva("");
886+
// ^
887+
let completionA = await document.completions({ line: 0, character: 13 })
888+
889+
expect(completionA?.items.length).toBe(12289)
890+
891+
// return <Test className={cn("")} />;
892+
// ^
893+
let completionB = await document.completions({ line: 3, character: 30 })
894+
895+
expect(completionB?.items.length).toBe(12289)
896+
897+
// return <Test className={cn("")} />;
898+
// ^
899+
let completionC = await document.completions({ line: 7, character: 30 })
900+
901+
expect(completionC?.items.length).toBe(12289)
902+
903+
// let y = cva("");
904+
// ^
905+
let completionD = await document.completions({ line: 10, character: 13 })
906+
907+
expect(completionD?.items.length).toBe(12289)
908+
},
909+
})

packages/tailwindcss-language-service/src/completionProvider.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,9 @@ async function provideClassAttributeCompletions(
703703
position: Position,
704704
context?: CompletionContext,
705705
): Promise<CompletionList> {
706+
let current = document.offsetAt(position)
706707
let range: Range = {
707-
start: document.positionAt(Math.max(0, document.offsetAt(position) - SEARCH_RANGE)),
708+
start: document.positionAt(Math.max(0, current - SEARCH_RANGE)),
708709
end: position,
709710
}
710711

@@ -734,13 +735,17 @@ async function provideClassAttributeCompletions(
734735
let offset = document.offsetAt(boundary.range.start)
735736
let fnMatches = matchClassFunctions(str, settings.classFunctions)
736737

737-
fnMatches.forEach((match) => {
738+
for (let match of fnMatches) {
738739
if (match.index) match.index += offset
739-
})
740+
if (match.index > current) continue
740741

741-
matches.push(...fnMatches)
742+
matches.push(match)
743+
}
742744
}
743745

746+
// Make sure matches are sorted by index
747+
matches.sort((a, b) => a.index - b.index)
748+
744749
if (matches.length === 0) {
745750
return null
746751
}

packages/vscode-tailwindcss/CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Prerelease
44

5-
- Nothing yet!
5+
- Fix completions not showing for some class attributes when a class function exists in the document ([#1278](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1278))
66

77
# 0.14.10
88

0 commit comments

Comments
 (0)