Fixes#1002.
In the indented syntax, a selector list may continue onto another line
if the previous line ends with a comma. Previously, if there was a
comment after the comma, it wouldn't be recognized and the selector
would be broken in two (with the first selector having no properties).
This fixes the parser to ignore comments when looking for the comma at
the end of a line.
Also disables the formatting check to work around dart-lang/dart_style#940.
Avoid adding duplicate modules when importing forwarded stylesheets
In Google stylesheets that imported import-only stylesheets with many
forwards many of times, we were seeing Environment._globalModules grow
large enough that variable accesses were a problem. This addresses
that in several ways:
* Forwarded modules are now ignored if the module is already being
forwarded.
* Module equality is more intelligent, so that shadowed and forwarded
modules can be effectively de-duplicated.
* If a module would be fully shadowed by a later import *and* that
module has no CSS, we no longer add an empty ShadowedModule to the
module list.
This combines all targets into a single extender invocation, which is
more efficient and allows it to more aggressively do redundant
selector elimination.
Prior to this, the watcher handled all the logic around recompiling
stylesheets if an upstream file was deleted or added in a way that
could affect their import resolution. This left a gap where the
stylesheet graph wouldn't be aware that a newly-added file had become
upstream dependency of an existing downstream file, leading to
recompilation failures.
This commit fixes that by moving all that logic into the stylesheet
graph. The graph now has full and sole responsibility for providing a
consistent view of which stylesheets depend on one another even as the
shape of the graph changes, and the watcher is just a client of that
logic.
Closes#550
We had been lazily initializing this to be more efficient when no
global modules were used, but this meant that the object wasn't shared
with closures created for mixins and functions that were created when
it was still `null`, so later imported forwards weren't visible to
those members.
Doing this for variable *nodes* was breaking in extremely specific
circumstances:
* A null node is passed into setVariable() and, if source maps are
enabled, recorded in _variableNodes.
* Later on, getVariableNode() is called for that variable. Because
that variable's node is null, it calls
_getVariableNodeFromGlobalModule() even though the variable is
actually defined.
* _getVariableNodeFromGlobalModule() sets _lastVariableIndex to 0 on
the assumption that the variable is undefined, which turns out to be
incorrect in this specific case.
The next commit will fix the issue where a null node can be passed
into setVariable() when source maps are enabled, but it makes more
sense to assign the variable index to 0 in the variable access anyway,
since it happens first and isn't skipped when source maps are
disabled.
With the NNBD change to Dart, it's no longer safe to rely on an iterator returning `null` when it has hit the end (or before calling `moveNext` the first time). For non-nullable element types, it will have to throw instead.
This PR rewrites code that currently rely on a `null` value to recognize the end of an iterator.
When overloaded functions receive an incorrect number of positional
arguments, determine which overload has the most similar number of
arguments, and then correctly display that number in the error.
Closes#520sass/sass-spec#1496
For any @errors encountered in mixins or functions, use the call-site
(instead of the @error rule) as the span printed in the error message.
Closes#474
See sass/sass-spec#1494
In #827 I made configuration never be null, but this turns out to be
overkill: we still need a way for _loadModule() and _execute() to
distinguish between "use the existing configuration" (for @forward)
and "use no configuration" (for an unconfigured @use or
meta.load-module()). We now use null as a sentinel value there, while
still ensuring that _configuration is non-nullable.
Closes#854
We switched to *updating* selectors a while ago so that cloned rules
would continue to see updates in their selectors, but we were still
generating and tracking rules in the Extender. This caused skew
between what rules the extender knew about and what rules actually
existed in situations where rules were copied (such as when resolving
nested media queries).
There's no principled reason the extender needs to know about style
rules at all, so now it just tracks modifiable wrappers of selectors.
These are re-used even when style rules are cloned, so they're safe
from the skew problem.
Closes#843
We had been using null to represent an empty configuration, but that
caused problems when an empty map snuck its way in as well. Now we
always use maps, with a const empty map for the common case.
See sass/sass#2744
`AtRootRule.query` and `Declaration.value` can be null, so this should be checked before passing them on to `visitInterpolation` and `visitExpression`.