Fix most strong-mode errors.

This commit is contained in:
Natalie Weizenbaum 2016-08-12 15:24:27 -07:00
parent 1ea3619d93
commit 25f625af13
2 changed files with 68 additions and 42 deletions

View File

@ -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;

View File

@ -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);