Make package:html strong clean
R=jmesserly@google.com
Review URL: https://codereview.chromium.org//1971923002 .
diff --git a/.analysis_options b/.analysis_options
new file mode 100644
index 0000000..a10d4c5
--- /dev/null
+++ b/.analysis_options
@@ -0,0 +1,2 @@
+analyzer:
+ strong-mode: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4dbea39..3320989 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,14 @@
This file contains highlights of what changes on each version of the html
package.
+## 0.13.0
+
+ * **BREAKING** Fix all [strong mode][] errors and warnings.
+ This involved adding more precise types on some public APIs, which is why it
+ may break users.
+
+[strong mode]: https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
+
#### Pub version 0.12.2+2
* Support `csslib` versions `0.13.x`.
diff --git a/lib/dom.dart b/lib/dom.dart
index 9e64759..63182f6 100644
--- a/lib/dom.dart
+++ b/lib/dom.dart
@@ -742,16 +742,17 @@
// TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see
// http://code.google.com/p/dart/issues/detail?id=5371
- void setRange(int start, int rangeLength, List<Node> from,
+ void setRange(int start, int rangeLength, Iterable<Node> from,
[int startFrom = 0]) {
- if (from is NodeList) {
+ List<Node> from_ = from as List<Node>;
+ if (from_ is NodeList) {
// Note: this is presumed to make a copy
- from = from.sublist(startFrom, startFrom + rangeLength);
+ from_ = from_.sublist(startFrom, startFrom + rangeLength);
}
// Note: see comment in [addAll]. We need to be careful about the order of
// operations if [from] is also a NodeList.
for (int i = rangeLength - 1; i >= 0; i--) {
- this[start + i] = from[startFrom + i];
+ this[start + i] = from_[startFrom + i];
}
}
@@ -765,14 +766,14 @@
super.removeRange(start, rangeLength);
}
- void removeWhere(bool test(Element e)) {
+ void removeWhere(bool test(Node e)) {
for (var node in where(test)) {
node.parentNode = null;
}
super.removeWhere(test);
}
- void retainWhere(bool test(Element e)) {
+ void retainWhere(bool test(Node e)) {
for (var node in where((n) => !test(n))) {
node.parentNode = null;
}
@@ -786,11 +787,11 @@
super.insertAll(index, list);
}
- _flattenDocFragments(Iterable<Node> collection) {
+ List<Node> _flattenDocFragments(Iterable<Node> collection) {
// Note: this function serves two purposes:
// * it flattens document fragments
// * it creates a copy of [collections] when `collection is NodeList`.
- var result = [];
+ var result = <Node>[];
for (var node in collection) {
if (node is DocumentFragment) {
result.addAll(node.nodes);
@@ -860,7 +861,7 @@
}
}
- bool contains(Element element) {
+ bool contains(Object element) {
return element is Element && _childNodes.contains(element);
}
@@ -901,9 +902,10 @@
return result;
}
- Iterable map(f(Element element)) => _filtered.map(f);
+ Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(Element element)) => _filtered.map(f);
Iterable<Element> where(bool f(Element element)) => _filtered.where(f);
- Iterable expand(Iterable f(Element element)) => _filtered.expand(f);
+ Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(Element element)) =>
+ _filtered.expand(f);
void insert(int index, Element value) {
_childNodes.insert(index, value);
@@ -935,8 +937,8 @@
return _filtered.reduce(combine);
}
- dynamic fold(dynamic initialValue,
- dynamic combine(dynamic previousValue, Element element)) {
+ dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue,
+ dynamic/*=T*/ combine(var/*=T*/ previousValue, Element element)) {
return _filtered.fold(initialValue, combine);
}
@@ -968,10 +970,14 @@
List<Element> sublist(int start, [int end]) => _filtered.sublist(start, end);
Iterable<Element> getRange(int start, int end) =>
_filtered.getRange(start, end);
- int indexOf(Element element, [int start = 0]) =>
+ // TODO(sigmund): this should be typed Element, but we currently run into a
+ // bug where ListMixin<E>.indexOf() expects Object as the argument.
+ int indexOf(element, [int start = 0]) =>
_filtered.indexOf(element, start);
- int lastIndexOf(Element element, [int start = null]) {
+ // TODO(sigmund): this should be typed Element, but we currently run into a
+ // bug where ListMixin<E>.lastIndexOf() expects Object as the argument.
+ int lastIndexOf(element, [int start = null]) {
if (start == null) start = length - 1;
return _filtered.lastIndexOf(element, start);
}
diff --git a/lib/parser.dart b/lib/parser.dart
index dc95941..0575b3d 100644
--- a/lib/parser.dart
+++ b/lib/parser.dart
@@ -210,7 +210,7 @@
try {
mainLoop();
break;
- } on ReparseException catch (e) {
+ } on ReparseException catch (_) {
// Note: this happens if we start parsing but the character encoding
// changes. So we should only need to restart very early in the parse.
reset();
@@ -819,7 +819,8 @@
// helper methods
void insertHtmlElement() {
- tree.insertRoot(new StartTagToken("html", data: {}));
+ tree.insertRoot(new StartTagToken("html",
+ data: new LinkedHashMap<dynamic, String>()));
parser.phase = parser._beforeHeadPhase;
}
@@ -875,7 +876,8 @@
case 'html':
return startTagHtml(token);
case 'head':
- return startTagHead(token);
+ startTagHead(token);
+ return null;
default:
return startTagOther(token);
}
@@ -889,12 +891,14 @@
case "br":
return endTagImplyHead(token);
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
bool processEOF() {
- startTagHead(new StartTagToken("head", data: {}));
+ startTagHead(new StartTagToken("head",
+ data: new LinkedHashMap<dynamic, String>()));
return true;
}
@@ -903,7 +907,8 @@
}
Token processCharacters(CharactersToken token) {
- startTagHead(new StartTagToken("head", data: {}));
+ startTagHead(new StartTagToken("head",
+ data: new LinkedHashMap<dynamic, String>()));
return token;
}
@@ -918,12 +923,14 @@
}
Token startTagOther(StartTagToken token) {
- startTagHead(new StartTagToken("head", data: {}));
+ startTagHead(new StartTagToken("head",
+ data: new LinkedHashMap<dynamic, String>()));
return token;
}
Token endTagImplyHead(EndTagToken token) {
- startTagHead(new StartTagToken("head", data: {}));
+ startTagHead(new StartTagToken("head",
+ data: new LinkedHashMap<dynamic, String>()));
return token;
}
@@ -941,23 +948,29 @@
case "html":
return startTagHtml(token);
case "title":
- return startTagTitle(token);
+ startTagTitle(token);
+ return null;
case "noscript":
case "noframes":
case "style":
- return startTagNoScriptNoFramesStyle(token);
+ startTagNoScriptNoFramesStyle(token);
+ return null;
case "script":
- return startTagScript(token);
+ startTagScript(token);
+ return null;
case "base":
case "basefont":
case "bgsound":
case "command":
case "link":
- return startTagBaseLinkCommand(token);
+ startTagBaseLinkCommand(token);
+ return null;
case "meta":
- return startTagMeta(token);
+ startTagMeta(token);
+ return null;
case "head":
- return startTagHead(token);
+ startTagHead(token);
+ return null;
default:
return startTagOther(token);
}
@@ -966,13 +979,15 @@
processEndTag(EndTagToken token) {
switch (token.name) {
case "head":
- return endTagHead(token);
+ endTagHead(token);
+ return null;
case "br":
case "html":
case "body":
return endTagHtmlBodyBr(token);
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
@@ -1075,9 +1090,11 @@
case "html":
return startTagHtml(token);
case "body":
- return startTagBody(token);
+ startTagBody(token);
+ return null;
case "frameset":
- return startTagFrameset(token);
+ startTagFrameset(token);
+ return null;
case "base":
case "basefont":
case "bgsound":
@@ -1087,9 +1104,11 @@
case "script":
case "style":
case "title":
- return startTagFromHead(token);
+ startTagFromHead(token);
+ return null;
case "head":
- return startTagHead(token);
+ startTagHead(token);
+ return null;
default:
return startTagOther(token);
}
@@ -1102,7 +1121,8 @@
case "br":
return endTagHtmlBodyBr(token);
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
@@ -1164,7 +1184,8 @@
}
void anythingElse() {
- tree.insertElement(new StartTagToken("body", data: {}));
+ tree.insertElement(new StartTagToken("body",
+ data: new LinkedHashMap<dynamic, String>()));
parser.phase = parser._inBodyPhase;
parser.framesetOK = true;
}
@@ -1195,9 +1216,11 @@
case "title":
return startTagProcessInHead(token);
case "body":
- return startTagBody(token);
+ startTagBody(token);
+ return null;
case "frameset":
- return startTagFrameset(token);
+ startTagFrameset(token);
+ return null;
case "address":
case "article":
case "aside":
@@ -1221,7 +1244,8 @@
case "section":
case "summary":
case "ul":
- return startTagCloseP(token);
+ startTagCloseP(token);
+ return null;
// headingElements
case "h1":
case "h2":
@@ -1229,20 +1253,26 @@
case "h4":
case "h5":
case "h6":
- return startTagHeading(token);
+ startTagHeading(token);
+ return null;
case "pre":
case "listing":
- return startTagPreListing(token);
+ startTagPreListing(token);
+ return null;
case "form":
- return startTagForm(token);
+ startTagForm(token);
+ return null;
case "li":
case "dd":
case "dt":
- return startTagListItem(token);
+ startTagListItem(token);
+ return null;
case "plaintext":
- return startTagPlaintext(token);
+ startTagPlaintext(token);
+ return null;
case "a":
- return startTagA(token);
+ startTagA(token);
+ return null;
case "b":
case "big":
case "code":
@@ -1255,58 +1285,77 @@
case "strong":
case "tt":
case "u":
- return startTagFormatting(token);
+ startTagFormatting(token);
+ return null;
case "nobr":
- return startTagNobr(token);
+ startTagNobr(token);
+ return null;
case "button":
return startTagButton(token);
case "applet":
case "marquee":
case "object":
- return startTagAppletMarqueeObject(token);
+ startTagAppletMarqueeObject(token);
+ return null;
case "xmp":
- return startTagXmp(token);
+ startTagXmp(token);
+ return null;
case "table":
- return startTagTable(token);
+ startTagTable(token);
+ return null;
case "area":
case "br":
case "embed":
case "img":
case "keygen":
case "wbr":
- return startTagVoidFormatting(token);
+ startTagVoidFormatting(token);
+ return null;
case "param":
case "source":
case "track":
- return startTagParamSource(token);
+ startTagParamSource(token);
+ return null;
case "input":
- return startTagInput(token);
+ startTagInput(token);
+ return null;
case "hr":
- return startTagHr(token);
+ startTagHr(token);
+ return null;
case "image":
- return startTagImage(token);
+ startTagImage(token);
+ return null;
case "isindex":
- return startTagIsIndex(token);
+ startTagIsIndex(token);
+ return null;
case "textarea":
- return startTagTextarea(token);
+ startTagTextarea(token);
+ return null;
case "iframe":
- return startTagIFrame(token);
+ startTagIFrame(token);
+ return null;
case "noembed":
case "noframes":
case "noscript":
- return startTagRawtext(token);
+ startTagRawtext(token);
+ return null;
case "select":
- return startTagSelect(token);
+ startTagSelect(token);
+ return null;
case "rp":
case "rt":
- return startTagRpRt(token);
+ startTagRpRt(token);
+ return null;
case "option":
case "optgroup":
- return startTagOpt(token);
+ startTagOpt(token);
+ return null;
case "math":
- return startTagMath(token);
+ startTagMath(token);
+ return null;
case "svg":
- return startTagSvg(token);
+ startTagSvg(token);
+ return null;
case "caption":
case "col":
case "colgroup":
@@ -1318,7 +1367,8 @@
case "th":
case "thead":
case "tr":
- return startTagMisplaced(token);
+ startTagMisplaced(token);
+ return null;
default:
return startTagOther(token);
}
@@ -1327,7 +1377,8 @@
processEndTag(EndTagToken token) {
switch (token.name) {
case "body":
- return endTagBody(token);
+ endTagBody(token);
+ return null;
case "html":
return endTagHtml(token);
case "address":
@@ -1353,15 +1404,19 @@
case "section":
case "summary":
case "ul":
- return endTagBlock(token);
+ endTagBlock(token);
+ return null;
case "form":
- return endTagForm(token);
+ endTagForm(token);
+ return null;
case "p":
- return endTagP(token);
+ endTagP(token);
+ return null;
case "dd":
case "dt":
case "li":
- return endTagListItem(token);
+ endTagListItem(token);
+ return null;
// headingElements
case "h1":
case "h2":
@@ -1369,7 +1424,8 @@
case "h4":
case "h5":
case "h6":
- return endTagHeading(token);
+ endTagHeading(token);
+ return null;
case "a":
case "b":
case "big":
@@ -1384,15 +1440,19 @@
case "strong":
case "tt":
case "u":
- return endTagFormatting(token);
+ endTagFormatting(token);
+ return null;
case "applet":
case "marquee":
case "object":
- return endTagAppletMarqueeObject(token);
+ endTagAppletMarqueeObject(token);
+ return null;
case "br":
- return endTagBr(token);
+ endTagBr(token);
+ return null;
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
@@ -1733,28 +1793,31 @@
if (tree.formPointer != null) {
return;
}
- var formAttrs = {};
+ var formAttrs = new LinkedHashMap<dynamic, String>();
var dataAction = token.data["action"];
if (dataAction != null) {
formAttrs["action"] = dataAction;
}
processStartTag(new StartTagToken("form", data: formAttrs));
- processStartTag(new StartTagToken("hr", data: {}));
- processStartTag(new StartTagToken("label", data: {}));
+ processStartTag(new StartTagToken("hr",
+ data: new LinkedHashMap<dynamic, String>()));
+ processStartTag(new StartTagToken("label",
+ data: new LinkedHashMap<dynamic, String>()));
// XXX Localization ...
var prompt = token.data["prompt"];
if (prompt == null) {
prompt = "This is a searchable index. Enter search keywords: ";
}
processCharacters(new CharactersToken(prompt));
- var attributes = new LinkedHashMap.from(token.data);
+ var attributes = new LinkedHashMap<dynamic, String>.from(token.data);
attributes.remove('action');
attributes.remove('prompt');
attributes["name"] = "isindex";
processStartTag(new StartTagToken(
"input", data: attributes, selfClosing: token.selfClosing));
processEndTag(new EndTagToken("label"));
- processStartTag(new StartTagToken("hr", data: {}));
+ processStartTag(new StartTagToken("hr",
+ data: new LinkedHashMap<dynamic, String>()));
processEndTag(new EndTagToken("form"));
}
@@ -1857,7 +1920,8 @@
void endTagP(EndTagToken token) {
if (!tree.elementInScope("p", variant: "button")) {
- startTagCloseP(new StartTagToken("p", data: {}));
+ startTagCloseP(new StartTagToken("p",
+ data: new LinkedHashMap<dynamic, String>()));
parser.parseError(token.span, "unexpected-end-tag", {"name": "p"});
endTagP(new EndTagToken("p"));
} else {
@@ -1994,7 +2058,7 @@
}
/// The much-feared adoption agency algorithm.
- endTagFormatting(EndTagToken token) {
+ void endTagFormatting(EndTagToken token) {
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency
// TODO(jmesserly): the comments here don't match the numbered steps in the
// updated spec. This needs a pass over it to verify that it still matches.
@@ -2164,7 +2228,8 @@
"newName": "br element"
});
tree.reconstructActiveFormattingElements();
- tree.insertElement(new StartTagToken("br", data: {}));
+ tree.insertElement(new StartTagToken("br",
+ data: new LinkedHashMap<dynamic, String>()));
tree.openElements.removeLast();
}
@@ -2199,8 +2264,11 @@
}
processEndTag(EndTagToken token) {
- if (token.name == 'script') return endTagScript(token);
- return endTagOther(token);
+ if (token.name == 'script') {
+ endTagScript(token);
+ return null;
+ }
+ endTagOther(token);
}
Token processCharacters(CharactersToken token) {
@@ -2240,15 +2308,18 @@
case "html":
return startTagHtml(token);
case "caption":
- return startTagCaption(token);
+ startTagCaption(token);
+ return null;
case "colgroup":
- return startTagColgroup(token);
+ startTagColgroup(token);
+ return null;
case "col":
return startTagCol(token);
case "tbody":
case "tfoot":
case "thead":
- return startTagRowGroup(token);
+ startTagRowGroup(token);
+ return null;
case "td":
case "th":
case "tr":
@@ -2259,18 +2330,22 @@
case "script":
return startTagStyleScript(token);
case "input":
- return startTagInput(token);
+ startTagInput(token);
+ return null;
case "form":
- return startTagForm(token);
+ startTagForm(token);
+ return null;
default:
- return startTagOther(token);
+ startTagOther(token);
+ return null;
}
}
processEndTag(EndTagToken token) {
switch (token.name) {
case "table":
- return endTagTable(token);
+ endTagTable(token);
+ return null;
case "body":
case "caption":
case "col":
@@ -2282,9 +2357,11 @@
case "th":
case "thead":
case "tr":
- return endTagIgnore(token);
+ endTagIgnore(token);
+ return null;
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
@@ -2350,7 +2427,8 @@
}
Token startTagCol(StartTagToken token) {
- startTagColgroup(new StartTagToken("colgroup", data: {}));
+ startTagColgroup(new StartTagToken("colgroup",
+ data: new LinkedHashMap<dynamic, String>()));
return token;
}
@@ -2361,7 +2439,8 @@
}
Token startTagImplyTbody(StartTagToken token) {
- startTagRowGroup(new StartTagToken("tbody", data: {}));
+ startTagRowGroup(new StartTagToken("tbody",
+ data: new LinkedHashMap<dynamic, String>()));
return token;
}
@@ -2542,7 +2621,8 @@
processEndTag(EndTagToken token) {
switch (token.name) {
case "caption":
- return endTagCaption(token);
+ endTagCaption(token);
+ return null;
case "table":
return endTagTable(token);
case "body":
@@ -2555,7 +2635,8 @@
case "th":
case "thead":
case "tr":
- return endTagIgnore(token);
+ endTagIgnore(token);
+ return null;
default:
return endTagOther(token);
}
@@ -2641,7 +2722,8 @@
case "html":
return startTagHtml(token);
case "col":
- return startTagCol(token);
+ startTagCol(token);
+ return null;
default:
return startTagOther(token);
}
@@ -2650,9 +2732,11 @@
processEndTag(EndTagToken token) {
switch (token.name) {
case "colgroup":
- return endTagColgroup(token);
+ endTagColgroup(token);
+ return null;
case "col":
- return endTagCol(token);
+ endTagCol(token);
+ return null;
default:
return endTagOther(token);
}
@@ -2722,7 +2806,8 @@
case "html":
return startTagHtml(token);
case "tr":
- return startTagTr(token);
+ startTagTr(token);
+ return null;
case "td":
case "th":
return startTagTableCell(token);
@@ -2743,7 +2828,8 @@
case "tbody":
case "tfoot":
case "thead":
- return endTagTableRowGroup(token);
+ endTagTableRowGroup(token);
+ return null;
case "table":
return endTagTable(token);
case "body":
@@ -2754,7 +2840,8 @@
case "td":
case "th":
case "tr":
- return endTagIgnore(token);
+ endTagIgnore(token);
+ return null;
default:
return endTagOther(token);
}
@@ -2796,7 +2883,8 @@
Token startTagTableCell(StartTagToken token) {
parser.parseError(
token.span, "unexpected-cell-in-table-body", {"name": token.name});
- startTagTr(new StartTagToken("tr", data: {}));
+ startTagTr(new StartTagToken("tr",
+ data: new LinkedHashMap<dynamic, String>()));
return token;
}
@@ -2854,7 +2942,8 @@
return startTagHtml(token);
case "td":
case "th":
- return startTagTableCell(token);
+ startTagTableCell(token);
+ return null;
case "caption":
case "col":
case "colgroup":
@@ -2871,7 +2960,8 @@
processEndTag(EndTagToken token) {
switch (token.name) {
case "tr":
- return endTagTr(token);
+ endTagTr(token);
+ return null;
case "table":
return endTagTable(token);
case "tbody":
@@ -2885,7 +2975,8 @@
case "html":
case "td":
case "th":
- return endTagIgnore(token);
+ endTagIgnore(token);
+ return null;
default:
return endTagOther(token);
}
@@ -3009,13 +3100,15 @@
switch (token.name) {
case "td":
case "th":
- return endTagTableCell(token);
+ endTagTableCell(token);
+ return null;
case "body":
case "caption":
case "col":
case "colgroup":
case "html":
- return endTagIgnore(token);
+ endTagIgnore(token);
+ return null;
case "table":
case "tbody":
case "tfoot":
@@ -3109,11 +3202,14 @@
case "html":
return startTagHtml(token);
case "option":
- return startTagOption(token);
+ startTagOption(token);
+ return null;
case "optgroup":
- return startTagOptgroup(token);
+ startTagOptgroup(token);
+ return null;
case "select":
- return startTagSelect(token);
+ startTagSelect(token);
+ return null;
case "input":
case "keygen":
case "textarea":
@@ -3128,13 +3224,17 @@
processEndTag(EndTagToken token) {
switch (token.name) {
case "option":
- return endTagOption(token);
+ endTagOption(token);
+ return null;
case "optgroup":
- return endTagOptgroup(token);
+ endTagOptgroup(token);
+ return null;
case "select":
- return endTagSelect(token);
+ endTagSelect(token);
+ return null;
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
@@ -3504,7 +3604,10 @@
}
processEndTag(EndTagToken token) {
- if (token.name == "html") return endTagHtml(token);
+ if (token.name == "html") {
+ endTagHtml(token);
+ return null;
+ }
return endTagOther(token);
}
@@ -3566,9 +3669,11 @@
case "html":
return startTagHtml(token);
case "frameset":
- return startTagFrameset(token);
+ startTagFrameset(token);
+ return null;
case "frame":
- return startTagFrame(token);
+ startTagFrame(token);
+ return null;
case "noframes":
return startTagNoframes(token);
default:
@@ -3579,9 +3684,11 @@
processEndTag(EndTagToken token) {
switch (token.name) {
case "frameset":
- return endTagFrameset(token);
+ endTagFrameset(token);
+ return null;
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
@@ -3653,16 +3760,19 @@
case "noframes":
return startTagNoframes(token);
default:
- return startTagOther(token);
+ startTagOther(token);
+ return null;
}
}
processEndTag(EndTagToken token) {
switch (token.name) {
case "html":
- return endTagHtml(token);
+ endTagHtml(token);
+ return null;
default:
- return endTagOther(token);
+ endTagOther(token);
+ return null;
}
}
@@ -3748,7 +3858,8 @@
case "noframes":
return startTagNoFrames(token);
default:
- return startTagOther(token);
+ startTagOther(token);
+ return null;
}
}
diff --git a/lib/src/css_class_set.dart b/lib/src/css_class_set.dart
index 2e131a5..c7927b8 100644
--- a/lib/src/css_class_set.dart
+++ b/lib/src/css_class_set.dart
@@ -55,7 +55,7 @@
* This is the Dart equivalent of jQuery's
* [hasClass](http://api.jquery.com/hasClass/).
*/
- bool contains(String value);
+ bool contains(Object value);
/**
* Add the class [value] to element.
@@ -93,7 +93,7 @@
* This is the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
*/
- void removeAll(Iterable<String> iterable);
+ void removeAll(Iterable<Object> iterable);
/**
* Toggles all classes specified in [iterable] on element.
@@ -151,11 +151,11 @@
String join([String separator = ""]) => readClasses().join(separator);
- Iterable map(f(String element)) => readClasses().map(f);
+ Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(String e)) => readClasses().map(f);
Iterable<String> where(bool f(String element)) => readClasses().where(f);
- Iterable expand(Iterable f(String element)) => readClasses().expand(f);
+ Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(String element)) => readClasses().expand(f);
bool every(bool f(String element)) => readClasses().every(f);
@@ -171,8 +171,8 @@
return readClasses().reduce(combine);
}
- dynamic fold(dynamic initialValue,
- dynamic combine(dynamic previousValue, String element)) {
+ dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue,
+ dynamic/*=T*/ combine(var/*=T*/ previousValue, String element)) {
return readClasses().fold(initialValue, combine);
}
// interface Collection - END
@@ -184,10 +184,10 @@
* This is the Dart equivalent of jQuery's
* [hasClass](http://api.jquery.com/hasClass/).
*/
- bool contains(String value) => readClasses().contains(value);
+ bool contains(Object value) => readClasses().contains(value);
/** Lookup from the Set interface. Not interesting for a String set. */
- String lookup(String value) => contains(value) ? value : null;
+ String lookup(Object value) => contains(value) ? value as String : null;
/**
* Add the class [value] to element.
@@ -233,7 +233,7 @@
* This is the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
*/
- void removeAll(Iterable<String> iterable) {
+ void removeAll(Iterable<Object> iterable) {
modify((s) => s.removeAll(iterable));
}
@@ -251,7 +251,7 @@
iterable.forEach((e) => toggle(e, shouldAdd));
}
- void retainAll(Iterable<String> iterable) {
+ void retainAll(Iterable<Object> iterable) {
modify((s) => s.retainAll(iterable));
}
@@ -263,10 +263,10 @@
modify((s) => s.retainWhere(test));
}
- bool containsAll(Iterable<String> collection) =>
+ bool containsAll(Iterable<Object> collection) =>
readClasses().containsAll(collection);
- Set<String> intersection(Set<String> other) =>
+ Set<String> intersection(Set<Object> other) =>
readClasses().intersection(other);
Set<String> union(Set<String> other) => readClasses().union(other);
@@ -285,9 +285,9 @@
Iterable<String> skip(int n) => readClasses().skip(n);
Iterable<String> skipWhile(bool test(String value)) =>
readClasses().skipWhile(test);
- dynamic firstWhere(bool test(String value), {Object orElse()}) =>
+ String firstWhere(bool test(String value), {String orElse()}) =>
readClasses().firstWhere(test, orElse: orElse);
- dynamic lastWhere(bool test(String value), {Object orElse()}) =>
+ String lastWhere(bool test(String value), {String orElse()}) =>
readClasses().lastWhere(test, orElse: orElse);
String singleWhere(bool test(String value)) =>
readClasses().singleWhere(test);
diff --git a/lib/src/encoding_parser.dart b/lib/src/encoding_parser.dart
index fd64ff9..0b84989 100644
--- a/lib/src/encoding_parser.dart
+++ b/lib/src/encoding_parser.dart
@@ -121,6 +121,14 @@
}
}
+typedef bool _MethodHandler();
+
+class _DispatchEntry {
+ final String pattern;
+ final _MethodHandler handler;
+ _DispatchEntry(this.pattern, this.handler);
+}
+
/// Mini parser for detecting character encoding from meta elements.
class EncodingParser {
final EncodingBytes data;
@@ -133,19 +141,19 @@
String getEncoding() {
final methodDispatch = [
- ["<!--", handleComment],
- ["<meta", handleMeta],
- ["</", handlePossibleEndTag],
- ["<!", handleOther],
- ["<?", handleOther],
- ["<", handlePossibleStartTag]
+ new _DispatchEntry("<!--", handleComment),
+ new _DispatchEntry("<meta", handleMeta),
+ new _DispatchEntry("</", handlePossibleEndTag),
+ new _DispatchEntry("<!", handleOther),
+ new _DispatchEntry("<?", handleOther),
+ new _DispatchEntry("<", handlePossibleStartTag),
];
try {
for (;;) {
for (var dispatch in methodDispatch) {
- if (data.matchBytes(dispatch[0])) {
- var keepParsing = dispatch[1]();
+ if (data.matchBytes(dispatch.pattern)) {
+ var keepParsing = dispatch.handler();
if (keepParsing) break;
// We found an encoding. Stop.
@@ -154,7 +162,7 @@
}
data.position += 1;
}
- } on StateError catch (e) {
+ } on StateError catch (_) {
// Catch this here to match behavior of Python's StopIteration
// TODO(jmesserly): refactor to not use exceptions
}
@@ -352,12 +360,12 @@
try {
data.skipUntil(isWhitespace);
return data.slice(oldPosition, data.position);
- } on StateError catch (e) {
+ } on StateError catch (_) {
//Return the whole remaining value
return data.slice(oldPosition);
}
}
- } on StateError catch (e) {
+ } on StateError catch (_) {
return null;
}
}
diff --git a/lib/src/list_proxy.dart b/lib/src/list_proxy.dart
index 99acdb6..5df1ed4 100644
--- a/lib/src/list_proxy.dart
+++ b/lib/src/list_proxy.dart
@@ -20,11 +20,14 @@
// TODO(jmesserly): This should be on List.
// See http://code.google.com/p/dart/issues/detail?id=947
- bool remove(E item) {
- int i = indexOf(item);
- if (i == -1) return false;
- removeAt(i);
- return true;
+ bool remove(Object item) {
+ if (item is E) {
+ int i = indexOf(item);
+ if (i == -1) return false;
+ removeAt(i);
+ return true;
+ }
+ return false;
}
void insert(int index, E item) => _list.insert(index, item);
@@ -81,7 +84,7 @@
List<E> getRange(int start, int end) => _list.getRange(start, end);
- void setRange(int start, int length, List<E> from, [int startFrom = 0]) {
+ void setRange(int start, int length, Iterable<E> from, [int startFrom = 0]) {
_list.setRange(start, length, from, startFrom);
}
void removeRange(int start, int length) {
diff --git a/lib/src/query_selector.dart b/lib/src/query_selector.dart
index e586d1a..3aa45f2 100644
--- a/lib/src/query_selector.dart
+++ b/lib/src/query_selector.dart
@@ -3,6 +3,7 @@
import 'package:csslib/parser.dart' as css;
import 'package:csslib/parser.dart' show TokenKind;
+import 'package:csslib/src/messages.dart' show Message;
import 'package:csslib/visitor.dart'; // the CSSOM
import 'package:html/dom.dart';
import 'package:html/src/constants.dart' show isWhitespaceCC;
@@ -14,7 +15,7 @@
new SelectorEvaluator().querySelector(node, _parseSelectorList(selector));
List<Element> querySelectorAll(Node node, String selector) {
- var results = [];
+ var results = <Element>[];
new SelectorEvaluator().querySelectorAll(
node, _parseSelectorList(selector), results);
return results;
@@ -22,7 +23,7 @@
// http://dev.w3.org/csswg/selectors-4/#grouping
SelectorGroup _parseSelectorList(String selector) {
- var errors = [];
+ var errors = <Message>[];
var group = css.parseSelectorGroup(selector, errors: errors);
if (group == null || errors.isNotEmpty) {
throw new FormatException("'$selector' is not a valid selector: $errors");
diff --git a/lib/src/tokenizer.dart b/lib/src/tokenizer.dart
index 3273858..68cb6dc 100644
--- a/lib/src/tokenizer.dart
+++ b/lib/src/tokenizer.dart
@@ -12,7 +12,7 @@
// TODO(jmesserly): we could use a better data structure here like a trie, if
// we had it implemented in Dart.
Map<String, List<String>> entitiesByFirstChar = (() {
- var result = {};
+ var result = <String, List<String>>{};
for (var k in entities.keys) {
result.putIfAbsent(k[0], () => []).add(k);
}
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index fb58cf1..16837b0 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -43,7 +43,7 @@
}
// Like the python [:] operator.
-List slice(List list, int start, [int end]) {
+List/*<T>*/ slice/*<T>*/(List/*<T>*/ list, int start, [int end]) {
if (end == null) end = list.length;
if (end < 0) end += list.length;
diff --git a/pubspec.yaml b/pubspec.yaml
index 697d1c8..4a595c1 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,12 +1,12 @@
name: html
-version: 0.12.2+2
+version: 0.13.0
author: Dart Team <misc@dartlang.org>
description: A library for working with HTML documents. Previously known as html5lib.
homepage: https://github.com/dart-lang/html
environment:
sdk: '>=1.2.0 <2.0.0'
dependencies:
- csslib: '>=0.10.0 <0.14.0'
+ csslib: '>=0.13.2 <0.14.0'
source_span: '>=1.0.0 <2.0.0'
utf: '>=0.9.0 <0.10.0'
dev_dependencies:
diff --git a/test/dom_test.dart b/test/dom_test.dart
index d4e0809..404a488 100644
--- a/test/dom_test.dart
+++ b/test/dom_test.dart
@@ -26,8 +26,8 @@
test('getElementById', () {
var foo = doc.body.nodes[0];
var Foo = foo.nodes[2];
- expect(foo.id, 'foo');
- expect(Foo.id, 'Foo');
+ expect((foo as Element).id, 'foo');
+ expect((Foo as Element).id, 'Foo');
expect(doc.getElementById('foo'), foo);
expect(doc.getElementById('Foo'), Foo);
});
@@ -36,8 +36,8 @@
var foo = doc.body.nodes[0];
var barBaz = foo.nodes[0];
var quxBaz = foo.nodes[1];
- expect(barBaz.className, ' bar baz');
- expect(quxBaz.className, 'qux baz ');
+ expect((barBaz as Element).className, ' bar baz');
+ expect((quxBaz as Element).className, 'qux baz ');
expect(doc.getElementsByClassName('baz'), [barBaz, quxBaz]);
expect(doc.getElementsByClassName('bar '), [barBaz]);
expect(doc.getElementsByClassName(' qux'), [quxBaz]);
@@ -57,83 +57,83 @@
test('add', () {
var doc = parse('<body>');
doc.body.nodes.add(parseFragment('<x-foo>'));
- expect(doc.body.nodes[0].localName, 'x-foo');
+ expect((doc.body.nodes[0] as Element).localName, 'x-foo');
doc.body.nodes.add(parseFragment('<x-bar>'));
- expect(doc.body.nodes[1].localName, 'x-bar');
+ expect((doc.body.nodes[1] as Element).localName, 'x-bar');
});
test('addLast', () {
var doc = parse('<body>');
doc.body.nodes.addLast(parseFragment('<x-foo>'));
- expect(doc.body.nodes[0].localName, 'x-foo');
+ expect((doc.body.nodes[0] as Element).localName, 'x-foo');
doc.body.nodes.addLast(parseFragment('<x-bar>'));
- expect(doc.body.nodes[1].localName, 'x-bar');
+ expect((doc.body.nodes[1] as Element).localName, 'x-bar');
});
test('addAll', () {
var doc = parse('<body><x-a></x-a>');
doc.body.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]);
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'x-b');
- expect(doc.body.nodes[2].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'x-b');
+ expect((doc.body.nodes[2] as Element).localName, 'x-c');
});
test('insert', () {
var doc = parse('<body><x-a></x-a>');
doc.body.nodes.insert(0, parseFragment('<x-b></x-b><x-c></x-c>'));
- expect(doc.body.nodes[0].localName, 'x-b');
- expect(doc.body.nodes[1].localName, 'x-c');
- expect(doc.body.nodes[2].localName, 'x-a');
+ expect((doc.body.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body.nodes[2] as Element).localName, 'x-a');
doc = parse('<body><x-a></x-a>');
doc.body.nodes.insert(1, parseFragment('<x-b></x-b><x-c></x-c>'));
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'x-b');
- expect(doc.body.nodes[2].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'x-b');
+ expect((doc.body.nodes[2] as Element).localName, 'x-c');
doc = parse('<body><x-a></x-a>');
doc.body.nodes.insert(0, parseFragment('<x-b></x-b>'));
doc.body.nodes.insert(1, parseFragment('<x-c></x-c>'));
- expect(doc.body.nodes[0].localName, 'x-b');
- expect(doc.body.nodes[1].localName, 'x-c');
- expect(doc.body.nodes[2].localName, 'x-a');
+ expect((doc.body.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body.nodes[2] as Element).localName, 'x-a');
});
test('insertAll', () {
var doc = parse('<body><x-a></x-a>');
doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b><x-c></x-c>')]);
- expect(doc.body.nodes[0].localName, 'x-b');
- expect(doc.body.nodes[1].localName, 'x-c');
- expect(doc.body.nodes[2].localName, 'x-a');
+ expect((doc.body.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body.nodes[2] as Element).localName, 'x-a');
expect(doc.body.nodes.length, 3);
doc = parse('<body><x-a></x-a>');
doc.body.nodes.insertAll(1, [parseFragment('<x-b></x-b><x-c></x-c>')]);
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'x-b');
- expect(doc.body.nodes[2].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'x-b');
+ expect((doc.body.nodes[2] as Element).localName, 'x-c');
doc = parse('<body><x-a></x-a>');
doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b>')]);
doc.body.nodes.insertAll(1, [parseFragment('<x-c></x-c>')]);
- expect(doc.body.nodes[0].localName, 'x-b');
- expect(doc.body.nodes[1].localName, 'x-c');
- expect(doc.body.nodes[2].localName, 'x-a');
+ expect((doc.body.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body.nodes[1] as Element).localName, 'x-c');
+ expect((doc.body.nodes[2] as Element).localName, 'x-a');
});
test('operator []=', () {
var doc = parse('<body><x-a></x-a>');
doc.body.nodes[0] = parseFragment('<x-b></x-b><x-c></x-c>');
- expect(doc.body.nodes[0].localName, 'x-b');
- expect(doc.body.nodes[1].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-b');
+ expect((doc.body.nodes[1] as Element).localName, 'x-c');
expect(doc.body.nodes.length, 2);
doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
doc.body.nodes[1] = parseFragment('<y-b></y-b><y-c></y-c>');
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'y-b');
- expect(doc.body.nodes[2].localName, 'y-c');
- expect(doc.body.nodes[3].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body.nodes[3] as Element).localName, 'x-c');
expect(doc.body.nodes.length, 4);
});
@@ -141,18 +141,18 @@
var fragment = parseFragment('<y-b></y-b><y-c></y-c>');
var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
doc.body.nodes.setRange(1, 2, fragment.nodes, 0);
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'y-b');
- expect(doc.body.nodes[2].localName, 'y-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body.nodes[2] as Element).localName, 'y-c');
expect(doc.body.nodes.length, 3);
fragment = parseFragment('<y-b></y-b><y-c></y-c>');
doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
doc.body.nodes.setRange(1, 1, [fragment], 0);
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'y-b');
- expect(doc.body.nodes[2].localName, 'y-c');
- expect(doc.body.nodes[3].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body.nodes[3] as Element).localName, 'x-c');
expect(doc.body.nodes.length, 4);
});
@@ -160,19 +160,19 @@
var fragment = parseFragment('<y-b></y-b><y-c></y-c>');
var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
doc.body.nodes.replaceRange(1, 2, fragment.nodes);
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'y-b');
- expect(doc.body.nodes[2].localName, 'y-c');
- expect(doc.body.nodes[3].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body.nodes[3] as Element).localName, 'x-c');
expect(doc.body.nodes.length, 4);
fragment = parseFragment('<y-b></y-b><y-c></y-c>');
doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
doc.body.nodes.replaceRange(1, 2, [fragment]);
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'y-b');
- expect(doc.body.nodes[2].localName, 'y-c');
- expect(doc.body.nodes[3].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body.nodes[3] as Element).localName, 'x-c');
expect(doc.body.nodes.length, 4);
});
@@ -180,10 +180,10 @@
var fragment = parseFragment('<y-b></y-b><y-c></y-c>');
var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>');
doc.body.nodes[1].replaceWith(fragment);
- expect(doc.body.nodes[0].localName, 'x-a');
- expect(doc.body.nodes[1].localName, 'y-b');
- expect(doc.body.nodes[2].localName, 'y-c');
- expect(doc.body.nodes[3].localName, 'x-c');
+ expect((doc.body.nodes[0] as Element).localName, 'x-a');
+ expect((doc.body.nodes[1] as Element).localName, 'y-b');
+ expect((doc.body.nodes[2] as Element).localName, 'y-c');
+ expect((doc.body.nodes[3] as Element).localName, 'x-c');
expect(doc.body.nodes.length, 4);
});
});
diff --git a/test/parser_feature_test.dart b/test/parser_feature_test.dart
index 54d68a9..6d3af0c 100644
--- a/test/parser_feature_test.dart
+++ b/test/parser_feature_test.dart
@@ -25,12 +25,12 @@
test('namespace html elements on', () {
var doc = new HtmlParser('', tree: new TreeBuilder(true)).parse();
- expect(doc.nodes[0].namespaceUri, Namespaces.html);
+ expect((doc.nodes[0] as Element).namespaceUri, Namespaces.html);
});
test('namespace html elements off', () {
var doc = new HtmlParser('', tree: new TreeBuilder(false)).parse();
- expect(doc.nodes[0].namespaceUri, null);
+ expect((doc.nodes[0] as Element).namespaceUri, null);
});
test('parse error spans - full', () {
@@ -290,7 +290,7 @@
expect(e.text, 'bar');
c.text = 'qux';
- expect(c.data, 'qux');
+ expect((c as Comment).data, 'qux');
expect(c.text, 'qux');
expect(e.text, 'bar');
});
@@ -310,7 +310,7 @@
});
group('Encoding pre-parser', () {
- getEncoding(s) => new EncodingParser(s.codeUnits).getEncoding();
+ getEncoding(String s) => new EncodingParser(s.codeUnits).getEncoding();
test('gets encoding from meta charset', () {
expect(getEncoding('<meta charset="utf-16">'), 'utf-16');
@@ -473,4 +473,4 @@
}
});
});
-}
\ No newline at end of file
+}
diff --git a/test/run_all.dart b/test/run_all.dart
index 14e6b34..d2bf9ce 100644
--- a/test/run_all.dart
+++ b/test/run_all.dart
@@ -17,7 +17,7 @@
var pattern = new RegExp(args.length > 0 ? args[0] : '.');
useCompactVMConfiguration();
- void addGroup(testFile, testMain) {
+ void addGroup(testFile, void testMain()) {
if (pattern.hasMatch(testFile)) {
group(testFile.replaceAll('_test.dart', ':'), testMain);
}
diff --git a/test/support.dart b/test/support.dart
index 1b4c0b4..1bb2550 100644
--- a/test/support.dart
+++ b/test/support.dart
@@ -10,7 +10,7 @@
typedef TreeBuilder TreeBuilderFactory(bool namespaceHTMLElements);
-Map _treeTypes;
+Map<String, TreeBuilderFactory> _treeTypes;
Map<String, TreeBuilderFactory> get treeTypes {
if (_treeTypes == null) {
// TODO(jmesserly): add DOM here once it's implemented
@@ -133,13 +133,16 @@
indent -= 2;
}
- visitDocument(node) {
+ visitDocument(node) => _visitDocumentOrFragment(node);
+
+ _visitDocumentOrFragment(node) {
indent += 1;
for (var child in node.nodes) visit(child);
indent -= 1;
}
- visitDocumentFragment(DocumentFragment node) => visitDocument(node);
+ visitDocumentFragment(DocumentFragment node) =>
+ _visitDocumentOrFragment(node);
visitElement(Element node) {
_newline();