* Add fatal/futureDeprecations to Dart API
This adds a new `Deprecation` class that specifies an ID for each
deprecated feature along with what Dart Sass version deprecated it.
The compile functions allow you to pass a set of `fatalDeprecations`
that will cause an error instead of a warning. You can also pass a set
of `futureDeprecations`, which let you opt-in to deprecations (like
`@import`) early.
* Add future deprecation for `@import`
* Add flags
* Merge colorUnits and randomWithUnits
* Update changelogs and pubspecs
* Add tests
* Use isFuture instead of deprecatedIn == null
* Split warnForDeprecation from warn
* Add missing word to error message
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.
The automatic @charset adding is useful in general, but there are
consistently cases where it trips up naïve downstream tools. This
option makes it easier for users to control when it occurs.
This adds a --no-unicode option to disable Unicode span rendering,
decouples repl highlighting from SourceSpan.highlight, and updates
tests to work with the new error highlighting.
It also tightly scopes source spans for statements with children.
Previously, source spans for these nodes extended all the way through
any whitespace that followed the node. This led to messy-looking
multiline span highlights with dart-lang/source_span#25.
Now, StylesheetParser.children doesn't consume trailing whitespace.
Instead, we add a helper method StylesheetParser._withChildren that
parses children, creates the appropriate span, and then consumes the
trailing whitespace.
This allows us to accurately track the source spans for parenthesized
expressions, which in turn allows us to print accurate error
indications.
Adding a new class for this more accurately represents the structure
of the expression, but it also involves an extra allocation during
parsing and an extra level of nesting during evaluation which could
have a small but real performance impact.
We could alternatively add a package-internal setter for
Expression.span, and update the source span for parenthesized
expressions after they're initially parsed. However, this has its own
downsides: it adds complexity and mutability to the object model; and
many expression classes currently use lazily-generated spans, so
making them settable would require adding extra slots on those
classes.
I decided to go with the extra class because it only adds overhead
when parentheses are actually used in practice, as opposed to adding
overhead to every list/color/etc. The runtime overhead is also likely
to be mitigated if at any point we add a constant-folding step.
When a stylesheet is imported, the parsed stylesheet object is cached
based on its canonical URL. However, the stylesheet.span.sourceUrl was
based on the text of the import that was used to load that stylesheet.
The idea was to make the source URL in stack traces look nicer, but it
meant that relative URLs could be resolved based on the old importer's
URL before being sent to the new importer, which caused bugs.
Now stylesheet.span.sourceUrl is always the canonical URL of the
stylesheet, and thus safe to cache. We then use the import cache to
convert the canonical URL to a human-friendly URL at the point at
which we generate stack traces.
This also deprecates support for relative canonical URLs. The
semantics of these URLs were always unclear, and with the new change
in import internals the old behavior doesn't make much sense. It's
preserved for backwards-compatibility, but deprecated.
If a non-partial stylesheet is next to a partial with the same name,
canonicalizing the source URL would fail. We don't really need to
canonicalize that URL anyway, though, since it's only used for import
loops and such a loop will reload and rerun the entrypoint anyway.