Skip to content

Commit

Permalink
Reload v4 design system when dependencies change (#1119)
Browse files Browse the repository at this point in the history
I noticed that editing imported CSS files, plugins, and configs in v4
the config wasn't reloading. This PR fixes that by making sure we reload
when any of them change.
  • Loading branch information
thecrypticace authored Jan 10, 2025
1 parent 001791a commit 3682d72
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 7 deletions.
35 changes: 35 additions & 0 deletions packages/tailwindcss-language-server/src/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export interface ProjectService {
onDocumentLinks(params: DocumentLinkParams): DocumentLink[]
sortClassLists(classLists: string[]): string[]

dependencies(): Iterable<string>
reload(): Promise<void>
}

Expand Down Expand Up @@ -186,6 +187,11 @@ export async function createProjectService(
getConfiguration: (uri?: string) => Promise<Settings>,
userLanguages: Record<string, string>,
): Promise<ProjectService> {
/* Project dependencies require a design system reload */
let dependencies = new Set<string>()

dependencies.add(projectConfig.configPath)

let enabled = false
const folder = projectConfig.folder
const disposables: Array<Disposable | Promise<Disposable>> = []
Expand Down Expand Up @@ -757,6 +763,14 @@ export async function createProjectService(

state.designSystem = designSystem

let deps = designSystem.dependencies()

for (let dep of deps) {
dependencies.add(dep)
}

watchPatterns(Array.from(deps))

originalConfig = { theme: {} }
} catch {
// TODO: Fall back to built-in v4 stuff
Expand Down Expand Up @@ -987,6 +1001,14 @@ export async function createProjectService(
updateCapabilities()
}

for (let entry of projectConfig.config.entries) {
dependencies.add(entry.path)

for (let dep of entry.deps) {
dependencies.add(dep.path)
}
}

return {
projectConfig,
enabled() {
Expand All @@ -996,6 +1018,7 @@ export async function createProjectService(
enabled = true
},

dependencies: () => dependencies,
async reload() {
if (!state.v4) return

Expand Down Expand Up @@ -1029,6 +1052,18 @@ export async function createProjectService(
state.classList = classList
state.variants = getVariants(state)

let deps = designSystem.dependencies()

for (let dep of deps) {
dependencies.add(dep)
}

watchPatterns(Array.from(deps))

// Update capabilities to force color swatches to update across editors
// TODO: Need to verify how well this works across various editors
// updateCapabilities()

console.log('---- RELOADED ----')
},

Expand Down
7 changes: 1 addition & 6 deletions packages/tailwindcss-language-server/src/tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,7 @@ export class TW {
for (let [, project] of this.projects) {
if (!project.state.v4) continue

let reloadableFiles = [
project.projectConfig.configPath,
...project.projectConfig.config.entries.map((entry) => entry.path),
]

if (!changeAffectsFile(normalizedFilename, reloadableFiles)) continue
if (!changeAffectsFile(normalizedFilename, project.dependencies())) continue

needsSoftRestart = true
break changeLoop
Expand Down
13 changes: 13 additions & 0 deletions packages/tailwindcss-language-server/src/util/v4/design-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ async function importFile(id: string) {
* everything from working so we'll let the error handler decide how to proceed.
*/
function createLoader<T>({
dependencies,
legacy,
filepath,
onError,
}: {
dependencies: Set<string>
legacy: boolean
filepath: string
onError: (id: string, error: unknown, resourceType: string) => T
Expand All @@ -58,6 +60,8 @@ function createLoader<T>({
try {
let resolved = resolveFrom(base, id)

dependencies.add(resolved)

let url = pathToFileURL(resolved)
url.searchParams.append('t', cacheKey)

Expand Down Expand Up @@ -93,6 +97,8 @@ export async function loadDesignSystem(
return null
}

let dependencies = new Set<string>()

let supportsImports = false
try {
await tailwindcss.__unstable__loadDesignSystem(css, {
Expand All @@ -115,6 +121,7 @@ export async function loadDesignSystem(

// v4.0.0-alpha.25+
loadModule: createLoader({
dependencies,
legacy: false,
filepath,
onError: (id, err, resourceType) => {
Expand All @@ -131,6 +138,8 @@ export async function loadDesignSystem(
loadStylesheet: async (id: string, base: string) => {
let resolved = resolveCssFrom(base, id)

dependencies.add(resolved)

return {
base: path.dirname(resolved),
content: await fs.readFile(resolved, 'utf-8'),
Expand All @@ -139,6 +148,7 @@ export async function loadDesignSystem(

// v4.0.0-alpha.24 and below
loadPlugin: createLoader({
dependencies,
legacy: true,
filepath,
onError(id, err) {
Expand All @@ -149,6 +159,7 @@ export async function loadDesignSystem(
}),

loadConfig: createLoader({
dependencies,
legacy: true,
filepath,
onError(id, err) {
Expand All @@ -161,6 +172,8 @@ export async function loadDesignSystem(

// Step 4: Augment the design system with some additional APIs that the LSP needs
Object.assign(design, {
dependencies: () => dependencies,

compile(classes: string[]): (postcss.Root | null)[] {
let css = design.candidatesToCss(classes)
let errors: any[] = []
Expand Down
2 changes: 1 addition & 1 deletion packages/tailwindcss-language-server/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function normalizeDriveLetter(filepath: string) {
return filepath.replace(WIN_DRIVE_LETTER, (_, letter) => letter.toUpperCase() + ':')
}

export function changeAffectsFile(change: string, files: string[]): boolean {
export function changeAffectsFile(change: string, files: Iterable<string>): boolean {
for (let file of files) {
if (change === file || dirContains(change, file)) {
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface DesignSystem {
}

export interface DesignSystem {
dependencies(): Set<string>
compile(classes: string[]): postcss.Root[]
toCss(nodes: postcss.Root | postcss.Node[]): string
}

0 comments on commit 3682d72

Please sign in to comment.