Skip to content

Commit

Permalink
Check extend usage after the fact.
Browse files Browse the repository at this point in the history
This means that extensions that match but fail to unify are valid, but
we think that's okay; see sass/sass#2250.
  • Loading branch information
nex3 committed May 26, 2017
1 parent 5e9a469 commit 1ae2221
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 15 deletions.
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -180,6 +180,9 @@ Sass to update the reference behavior.

14. Universal selector unification is symmetrical. See [issue 2247][].

15. `@extend` doesn't produce an error if it matches but fails to unify. See
[issue 2250][].

[issue 1599]: https://github.com/sass/sass/issues/1599
[issue 1126]: https://github.com/sass/sass/issues/1126
[issue 2120]: https://github.com/sass/sass/issues/2120
Expand All @@ -194,5 +197,6 @@ Sass to update the reference behavior.
[issue 2245]: https://github.com/sass/sass/issues/2245
[issue 303]: https://github.com/sass/sass/issues/303
[issue 2247]: https://github.com/sass/sass/issues/2247
[issue 2250]: https://github.com/sass/sass/issues/2250

Disclaimer: this is not an official Google product.
22 changes: 10 additions & 12 deletions lib/src/extend/extender.dart
Expand Up @@ -173,14 +173,12 @@ class Extender {
if (rules == null) return;
if (newExtenders == null) return;
for (var rule in rules) {
// A selector can't extend its own rule.
if (identical(rule.selector.value, extender)) continue;

try {
var extended = _extendList(
rule.selector.value = _extendList(
rule.selector.value, {target: newExtenders}, _mediaContexts[rule]);

// A selector can't extend its own rule. We still have to run the extend
// to set [state.isUsed] appropriately, though.
if (identical(rule.selector.value, extender)) continue;
rule.selector.value = extended;
} on SassException catch (error) {
throw new SassException(
"From ${rule.selector.span.message('')}\n"
Expand All @@ -195,13 +193,15 @@ class Extender {
/// Throws a [SassException] if any (non-optional) extensions failed to match
/// any selectors.
void finalize() {
_extensions.forEach((target, sources) {
sources.forEach((_, state) {
if (state.isOptional || state.isUsed) return;
_extensions.forEach((target, extensions) {
if (_selectors.containsKey(target)) return;

extensions.forEach((_, extension) {
if (extension.isOptional) return;
throw new SassException(
'The target selector was not found.\n'
'Use "@extend $target !optional" to avoid this error.',
state.span);
extension.span);
});
});
}
Expand Down Expand Up @@ -343,7 +343,6 @@ class Extender {
// need any unification.
if (options.length == 1) {
return options.first.map((state) {
state.isUsed = true;
state.assertCompatibleMediaContext(mediaQueryContext);
return state.extender;
}).toList();
Expand Down Expand Up @@ -416,7 +415,6 @@ class Extender {
var specificity = _sourceSpecificityFor(compound);
for (var state in path) {
state.assertCompatibleMediaContext(mediaQueryContext);
state.isUsed = true;
lineBreak = lineBreak || state.extender.lineBreak;
specificity = math.max(specificity, state.specificity);
}
Expand Down
3 changes: 0 additions & 3 deletions lib/src/extend/extension.dart
Expand Up @@ -29,9 +29,6 @@ class Extension {
/// originally in the document, rather than one defined with `@extend`.
final bool isOriginal;

/// Whether this extension matched a selector.
var isUsed = false;

/// The media query context to which this extend is restricted, or `null` if
/// it can apply within any context.
List<CssMediaQuery> get mediaContext => _mediaContext;
Expand Down

0 comments on commit 1ae2221

Please sign in to comment.