It is a bit of noise but it will ensure that we don't have false
positives. For example when you have the following code:
```js
it('should fail', () => {
return promise.catch((err) => {
expect(err).toBeInstanceOf(Error)
});
});
```
You would expect that the test passes because we have an expect in the
`.catch` block. However if the promise just resolves it means that no
assertions are executed and the test is considered successful. So in
this case it will _also_ call but for the incorrect reasons!
Naming is hard so I took this name from the React hook 😎
Also use this useMemoy utility to make sure that the extractUtilityNames
is cached. There is no need to re-compute the utility names all the
time.
We used to clone the full tree and then remove all the children, this
was a bit too slow so therefore we will now create a new tree based on
the old information.
We alreayd know that we have an `@apply` otherwise we would not have
called that function in the first place. Moving to a `do {} while ()`
allows us to skip 1 call to `hasAtRule(css, 'apply')`. Which is nice
because that skips a possible full traversal.
We create a big lookup table so that we can lookup the nodes by its
utilityName. This is used inside the recursive `@apply` code.
This big lookup table will clone every single rule and put it in,
however we don't need to clone everything! We are only interested in the
rules that have been actually applied.
This way we make the cloning of the rule lazy and only when we use this
exact rule.
There is an additional performace "issue" though: When we read the same
rule multiple times, it will clone every time you read from that object.
We could add additional memoization stuff, but so far it doesn't seem to
be the bottleneck. Therefore I've added a perf todo just to leave a mark
when this becomes the bottleneck.
Currently we will walk the tree for every single rule to see if an
`@apply` exists somewhere in that tree. However we don't use the
`containsApply` anymore so this is a quick win!