You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a request comes in to the language server for a document we have to
determine what project that document belongs to. This is because your
workspace can have many tailwind config files and potentially across
different Tailwind CSS versions.
The process for this happens in two stages:
1. Initialization computes a list of selectors for a project. These
selectors contain glob patterns that match a filepath to one or more
projects. In addition to the glob pattern is a priority which is a
"lowest match wins" scale. So things like user configured patterns in
settings are the most important, then your config files, then content
from the `content` array in v3 or detected sources in v4, approximate
path matches based on folder, etc…
2. When we get a request for hovers, completions, etc… we check every
project against the list of selectors to see if it matches and at what
priority. This involves compiling glob patterns.
The *lowest* priority match wins. If multiple projects match a document
at the same priority then first match wins. If a project contains a
selector that discards a particular document then that project is
removed from consideration before continuing.
Now for the problem, we were re-compiling globs *over and over and over
again*. Normally, for a small project this isn't an issue but automatic
content detection means that a large number of paths can be returned.
And if you have lots of projects? Welp… this adds up. What's more is
that when VSCode needed to compute document symbols requests were made
to our language server (… i don't know why actually) which then incurred
a perf hit caused by these globs being repeatedly recompiled… and since
this is effectively a single threaded operation it delays any waiting
promises.
So this PR does two things:
- It moves the sorting that was happening for every request for every
project to happen *during project initialization*. If selectors are
computed or recomputed they are sorted then. We do this sorting to move
the negative matchers to the front so we can disqualify files from
matching a project quicker.
- We cache the compiled matchers. This is especially important if you
have several v4 projects and many of them list the same paths.
In a realworld project this lowered the time to show suggestions from
emmet from **4 SECONDS** (omg) to about 15-20ms on an M3 Max machine.
aside: There was also sometimes a delay in time even getting completion
requests due to the single-threaded nature of JS. That could also end up
being multiple seconds. So in reality the time could be from range from
4–8s depending on when you made the request.
0 commit comments