mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-26 20:24:42 +01:00
Fix most strong-mode errors.
This commit is contained in:
parent
1ea3619d93
commit
25f625af13
@ -3,7 +3,9 @@
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../ast/css/node.dart';
|
||||
@ -23,9 +25,10 @@ class Extender {
|
||||
|
||||
final _sources = new Expando<ComplexSelector>();
|
||||
|
||||
CssStyleRule addSelector(SelectorList selector, {FileSpan selectorSpan,
|
||||
FileSpan ruleSpan}) {
|
||||
for (var complex in selector.components) {
|
||||
CssStyleRule addSelector(CssValue<SelectorList> selectorValue,
|
||||
{FileSpan span}) {
|
||||
var selector = selectorValue.value;
|
||||
for (var complex in selector.value.components) {
|
||||
for (var component in complex.components) {
|
||||
if (component is CompoundSelector) {
|
||||
for (var simple in component.components) {
|
||||
@ -36,9 +39,7 @@ class Extender {
|
||||
}
|
||||
|
||||
if (_extensions.isNotEmpty) selector = _extendList(selector, _extensions);
|
||||
var rule = new CssStyleRule(
|
||||
new CssValue(selector, span: selectorSpan),
|
||||
span: ruleSpan);
|
||||
var rule = new CssStyleRule(selectorValue, span: span);
|
||||
|
||||
for (var complex in selector.components) {
|
||||
for (var component in complex.components) {
|
||||
@ -117,7 +118,7 @@ class Extender {
|
||||
if (!changed) return null;
|
||||
|
||||
// TODO: preserve line breaks
|
||||
var weaves = paths(extendedNotExpanded)
|
||||
var weaves = _paths(extendedNotExpanded)
|
||||
.map((path) => _weave(path))
|
||||
.toList();
|
||||
return _trim(weaves).map((complex) => new ComplexSelector(complex));
|
||||
@ -210,7 +211,8 @@ class Extender {
|
||||
|
||||
var groups1 = _groupSelectors(queue1);
|
||||
var groups2 = _groupSelectors(queue2);
|
||||
var lcs = longestCommonSubsequence(groups1, groups2, (group1, group2) {
|
||||
var lcs = longestCommonSubsequence(groups1, groups2,
|
||||
select: (group1, group2) {
|
||||
if (listEquals(group1, group2)) return group1;
|
||||
if (group1.first is! CompoundSelector ||
|
||||
group2.first is! CompoundSelector) {
|
||||
@ -226,18 +228,20 @@ class Extender {
|
||||
return unified.first;
|
||||
});
|
||||
|
||||
var choices = [[initialCombinator]];
|
||||
var choices = [<List<ComplexSelectorComponent>>[initialCombinator]];
|
||||
for (var group in lcs) {
|
||||
choices.add(_chunks(groups1, groups2,
|
||||
(sequence) => _isParentSuperselector(sequence.first, group)));
|
||||
(sequence) => _isParentSuperselector(sequence.first, group))
|
||||
.map((chunk) => chunk.expand((group) => group)));
|
||||
choices.add(group);
|
||||
groups1.removeFirst();
|
||||
groups2.removeFirst();
|
||||
}
|
||||
choices.add(_chunks(groups1, groups2, (sequence) => sequence.isEmpty));
|
||||
choices.add(_chunks(groups1, groups2, (sequence) => sequence.isEmpty)
|
||||
.map((chunk) => chunk.expand((group) => group)));
|
||||
choices.addAll(finalCombinator);
|
||||
|
||||
return paths(choices.where((choice) => choice.isNotEmpty))
|
||||
return _paths(choices.where((choice) => choice.isNotEmpty))
|
||||
.map((path) => path.expand((group) => group));
|
||||
}
|
||||
|
||||
@ -246,17 +250,17 @@ class Extender {
|
||||
Queue<ComplexSelectorComponent> components2) {
|
||||
var combinators1 = <Combinator>[];
|
||||
while (components1.first is Combinator) {
|
||||
combinators1.add(components1.first as Combinator);
|
||||
combinators1.add(components1.removeFirst() as Combinator);
|
||||
}
|
||||
|
||||
var combinators2 = <Combinator>[];
|
||||
while (components2.first is Combinator) {
|
||||
combinators2.add(components2.first as Combinator);
|
||||
combinators2.add(components2.removeFirst() as Combinator);
|
||||
}
|
||||
|
||||
// If neither sequence of combinators is a subsequence of the other, they
|
||||
// cannot be merged successfully.
|
||||
var lcs = leastCommonSubsequence(combinators1, combinators2);
|
||||
var lcs = longestCommonSubsequence(combinators1, combinators2);
|
||||
if (listEquals(lcs, combinators1)) return combinators2;
|
||||
if (listEquals(lcs, combinators2)) return combinators1;
|
||||
return null;
|
||||
@ -285,11 +289,11 @@ class Extender {
|
||||
if (combinators1.length > 1 || combinators2.length > 1) {
|
||||
// If there are multiple combinators, something hacky's going on. If one
|
||||
// is a supersequence of the other, use that, otherwise give up.
|
||||
var lcs = leastCommonSubsequence(combinators1, combinators2);
|
||||
var lcs = longestCommonSubsequence(combinators1, combinators2);
|
||||
if (listEquals(lcs, combinators1)) {
|
||||
result.addAll(combinators2.reversed);
|
||||
result.addAll([new List.from(combinators2.reversed)]);
|
||||
} else if (listEquals(lcs, combinators2)) {
|
||||
result.addAll(combinators1.reversed);
|
||||
result.addAll([new List.from(combinators1.reversed)]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -367,7 +371,7 @@ class Extender {
|
||||
var unified = _unifyCompound(
|
||||
compound1.components, compound2.components);
|
||||
if (unified == null) return null;
|
||||
result.addFirst([[merged, combinator1]]);
|
||||
result.addFirst([[unified, combinator1]]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -376,7 +380,7 @@ class Extender {
|
||||
} else if (combinator1 != null) {
|
||||
if (combinator1 == Combinator.child &&
|
||||
components2.isNotEmpty &&
|
||||
components2.last.isSuperselector(components1.last)) {
|
||||
(components2.last as CompoundSelector).isSuperselector(components1.last)) {
|
||||
components2.removeLast();
|
||||
}
|
||||
result.addFirst([[components1.removeLast(), combinator1]]);
|
||||
@ -385,7 +389,7 @@ class Extender {
|
||||
assert(combinator1 != null);
|
||||
if (combinator2 == Combinator.child &&
|
||||
components1.isNotEmpty &&
|
||||
components1.last.isSuperselector(components2.last)) {
|
||||
(components1.last as CompoundSelector).isSuperselector(components2.last)) {
|
||||
components1.removeLast();
|
||||
}
|
||||
result.addFirst([[components2.removeLast(), combinator2]]);
|
||||
@ -393,8 +397,8 @@ class Extender {
|
||||
}
|
||||
}
|
||||
|
||||
List<List/*<T>*/> _chunks/*<T>*/(Queue<List/*<T>*/> queue1,
|
||||
Queue<List/*<T>*/> queue2, bool done(Queue<List/*<T>*/> queue)) {
|
||||
List<List/*<T>*/> _chunks/*<T>*/(Queue/*<T>*/ queue1,
|
||||
Queue/*<T>*/ queue2, bool done(Queue/*<T>*/ queue)) {
|
||||
var chunk1 = /*<T>*/[];
|
||||
while (!done(queue1)) {
|
||||
chunk1.add(queue1.removeFirst());
|
||||
@ -408,12 +412,12 @@ class Extender {
|
||||
if (chunk1.isEmpty && chunk2.isEmpty) return [];
|
||||
if (chunk1.isEmpty) return [chunk2];
|
||||
if (chunk2.isEmpty) return [chunk1];
|
||||
return [chunk1.toList()..addAll(chunk2), chunk2.addAll(chunk1)];
|
||||
return [chunk1.toList()..addAll(chunk2), chunk2..addAll(chunk1)];
|
||||
}
|
||||
|
||||
Queue<List<ComplexSelectorComponent>> _groupSelectors(
|
||||
QueueList<List<ComplexSelectorComponent>> _groupSelectors(
|
||||
Iterable<ComplexSelectorComponent> complex) {
|
||||
var groups = new Queue<List<ComplexSelectorComponent>>();
|
||||
var groups = new QueueList<List<ComplexSelectorComponent>>();
|
||||
var iterator = complex.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
var group = <ComplexSelectorComponent>[];
|
||||
@ -433,7 +437,7 @@ class Extender {
|
||||
// TODO(nweiz): I think there may be a way to get perfect trimming without
|
||||
// going quadratic by building some sort of trie-like data structure that
|
||||
// can be used to look up superselectors.
|
||||
if (path.length > 100) return weave.expand((selectors) => selectors);
|
||||
if (lists.length > 100) return lists.expand((selectors) => selectors);
|
||||
|
||||
// This is n² on the sequences, but only comparing between separate
|
||||
// sequences should limit the quadratic behavior.
|
||||
@ -445,7 +449,7 @@ class Extender {
|
||||
// another selector that's a superselector of it *and* that has
|
||||
// specificity greater or equal to this.
|
||||
var maxSpecificity = 0;
|
||||
for (var component in complex1.components) {
|
||||
for (var component in complex1) {
|
||||
if (component is CompoundSelector) {
|
||||
for (var simple in component.components) {
|
||||
var source = _sources[simple];
|
||||
@ -460,15 +464,17 @@ class Extender {
|
||||
// been trimmed, and thus that if there are two identical selectors only
|
||||
// one is trimmed.
|
||||
if (result.any((complex2) =>
|
||||
complex2.minSpecificity >= maxSpecificity &&
|
||||
_complexMinSpecificity(complex2) >= maxSpecificity &&
|
||||
complexIsSuperselector(complex2, complex1))) {
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lists.skip(i + 1).any((complex2) =>
|
||||
complex2.minSpecificity >= maxSpecificity &&
|
||||
complexIsSuperselector(complex2, complex1))) {
|
||||
return false;
|
||||
// We intentionally don't compare [complex1] against other selectors in
|
||||
// `lists[i]`, since they come from the same source.
|
||||
if (lists.skip(i + 1).any((list) => list.any((complex2) =>
|
||||
_complexMinSpecificity(complex2) >= maxSpecificity &&
|
||||
complexIsSuperselector(complex2, complex1)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(complex1);
|
||||
@ -478,18 +484,34 @@ class Extender {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<List<ComplexSelectorComponent> _unifyComplex(
|
||||
List<SimpleSelector> complex1, List<SimpleSelector> complex2) {
|
||||
var base1 = complex1.components.last;
|
||||
var base2 = complex2.components.last;
|
||||
int _complexMinSpecificity(Iterable<ComplexSelectorComponent> complex) {
|
||||
var result = 0;
|
||||
for (var component in complex) {
|
||||
if (component is CompoundSelector) {
|
||||
result += component.minSpecificity;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool _hasRoot(CompoundSelector compound) =>
|
||||
compound.components.any((simple) =>
|
||||
simple is PseudoSelector &&
|
||||
simple.type == PseudoType.klass &&
|
||||
simple.normalizedName == 'root');
|
||||
|
||||
List<List<ComplexSelectorComponent>> _unifyComplex(
|
||||
List<ComplexSelectorComponent> complex1,
|
||||
List<ComplexSelectorComponent> complex2) {
|
||||
var base1 = complex1.last;
|
||||
var base2 = complex2.last;
|
||||
if (base1 is CompoundSelector && base2 is CompoundSelector) {
|
||||
var unified = _unifyCompound(base2.components, base1.components);
|
||||
if (unified == null) return null;
|
||||
|
||||
return weave([
|
||||
base1.components.take(base1.components.length - 1).toList(),
|
||||
base2.components.take(base2.components.length - 1).toList()
|
||||
..add(unified)
|
||||
return _weave([
|
||||
complex1.take(complex1.length - 1).toList(),
|
||||
complex2.take(complex2.length - 1).toList()..add(unified)
|
||||
]);
|
||||
} else {
|
||||
return null;
|
||||
|
@ -6,6 +6,7 @@ import 'dart:collection';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:charcode/charcode.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import 'ast/node.dart';
|
||||
@ -20,6 +21,9 @@ class LinkedListValue<T> extends LinkedListEntry<LinkedListValue<T>> {
|
||||
LinkedListValue(this.value);
|
||||
}
|
||||
|
||||
bool listEquals/*<T>*/(List/*<T>*/ list1, List/*<T>*/ list2) =>
|
||||
const ListEquality().equals(list1, list2);
|
||||
|
||||
FileSpan spanForList(List<AstNode> nodes) {
|
||||
if (nodes.isEmpty) return null;
|
||||
return nodes.first.span.expand(nodes.last.span);
|
||||
|
Loading…
Reference in New Issue
Block a user