| OLD | NEW |
| 1 // This code was auto-generated, is not intended to be edited, and is subject to | 1 // This code was auto-generated, is not intended to be edited, and is subject to |
| 2 // significant change. Please see the README file for more information. | 2 // significant change. Please see the README file for more information. |
| 3 | 3 |
| 4 library engine.html; | 4 library engine.html; |
| 5 | 5 |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import 'java_core.dart'; | 7 import 'java_core.dart'; |
| 8 import 'java_engine.dart'; | 8 import 'java_engine.dart'; |
| 9 import 'source.dart'; | 9 import 'source.dart'; |
| 10 import 'element.dart' show HtmlElementImpl; | 10 import 'error.dart' show AnalysisErrorListener; |
| 11 import 'scanner.dart' as sc show Scanner, SubSequenceReader, Token; |
| 12 import 'parser.dart' show Parser; |
| 13 import 'ast.dart' show ASTVisitor, CompilationUnit, Expression; |
| 14 import 'element.dart' show HtmlElementImpl, HtmlScriptElement; |
| 11 import 'engine.dart' show AnalysisEngine; | 15 import 'engine.dart' show AnalysisEngine; |
| 12 | 16 |
| 13 /** | 17 /** |
| 14 * Instances of the class `Token` represent a token that was scanned from the in
put. Each | 18 * Instances of the class `Token` represent a token that was scanned from the in
put. Each |
| 15 * token knows which token follows it, acting as the head of a linked list of to
kens. | 19 * token knows which token follows it, acting as the head of a linked list of to
kens. |
| 16 * | 20 * |
| 17 * @coverage dart.engine.html | 21 * @coverage dart.engine.html |
| 18 */ | 22 */ |
| 19 class Token { | 23 class Token { |
| 20 /** | 24 /** |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 Token setNext(Token token) { | 102 Token setNext(Token token) { |
| 99 next = token; | 103 next = token; |
| 100 token.previous = this; | 104 token.previous = this; |
| 101 return token; | 105 return token; |
| 102 } | 106 } |
| 103 | 107 |
| 104 String toString() => lexeme; | 108 String toString() => lexeme; |
| 105 } | 109 } |
| 106 | 110 |
| 107 /** | 111 /** |
| 112 * Instances of the class `EmbeddedExpression` represent an expression enclosed
between |
| 113 * <code>{{</code> and <code>}}</code> delimiters. |
| 114 */ |
| 115 class EmbeddedExpression { |
| 116 /** |
| 117 * The offset of the first character of the opening delimiter. |
| 118 */ |
| 119 int openingOffset = 0; |
| 120 |
| 121 /** |
| 122 * The expression that is enclosed between the delimiters. |
| 123 */ |
| 124 Expression expression; |
| 125 |
| 126 /** |
| 127 * The offset of the first character of the closing delimiter. |
| 128 */ |
| 129 int closingOffset = 0; |
| 130 |
| 131 /** |
| 132 * An empty array of embedded expressions. |
| 133 */ |
| 134 static List<EmbeddedExpression> EMPTY_ARRAY = new List<EmbeddedExpression>(0); |
| 135 |
| 136 /** |
| 137 * Initialize a newly created embedded expression to represent the given expre
ssion. |
| 138 * |
| 139 * @param openingOffset the offset of the first character of the opening delim
iter |
| 140 * @param expression the expression that is enclosed between the delimiters |
| 141 * @param closingOffset the offset of the first character of the closing delim
iter |
| 142 */ |
| 143 EmbeddedExpression(int openingOffset, Expression expression, int closingOffset
) { |
| 144 this.openingOffset = openingOffset; |
| 145 this.expression = expression; |
| 146 this.closingOffset = closingOffset; |
| 147 } |
| 148 } |
| 149 |
| 150 /** |
| 108 * Instances of `HtmlParseResult` hold the result of parsing an HTML file. | 151 * Instances of `HtmlParseResult` hold the result of parsing an HTML file. |
| 109 * | 152 * |
| 110 * @coverage dart.engine.html | 153 * @coverage dart.engine.html |
| 111 */ | 154 */ |
| 112 class HtmlParseResult extends HtmlScanResult { | 155 class HtmlParseResult extends HtmlScanResult { |
| 113 /** | 156 /** |
| 114 * The unit containing the parsed information (not `null`). | 157 * The unit containing the parsed information (not `null`). |
| 115 */ | 158 */ |
| 116 HtmlUnit htmlUnit; | 159 HtmlUnit htmlUnit; |
| 117 | 160 |
| 118 HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlU
nit unit) : super(modificationTime, token, lineStarts) { | 161 HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlU
nit unit) : super(modificationTime, token, lineStarts) { |
| 119 this.htmlUnit = unit; | 162 this.htmlUnit = unit; |
| 120 } | 163 } |
| 121 } | 164 } |
| 122 | 165 |
| 123 /** | 166 /** |
| 167 * Instances of the class `TagWithEmbeddedExpressions` represent a tag whose tex
t content |
| 168 * contains one or more embedded expressions. |
| 169 */ |
| 170 class TagWithEmbeddedExpressions extends XmlTagNode { |
| 171 /** |
| 172 * The expressions that are embedded in the tag's content. |
| 173 */ |
| 174 List<EmbeddedExpression> _expressions; |
| 175 |
| 176 /** |
| 177 * Initialize a newly created tag whose text content contains one or more embe
dded expressions. |
| 178 * |
| 179 * @param nodeStart the token marking the beginning of the tag |
| 180 * @param tag the name of the tag |
| 181 * @param attributes the attributes in the tag |
| 182 * @param attributeEnd the token terminating the region where attributes can b
e |
| 183 * @param tagNodes the children of the tag |
| 184 * @param contentEnd the token that starts the closing tag |
| 185 * @param closingTag the name of the tag that occurs in the closing tag |
| 186 * @param nodeEnd the last token in the tag |
| 187 * @param expressions the expressions that are embedded in the value |
| 188 */ |
| 189 TagWithEmbeddedExpressions(Token nodeStart, Token tag, List<XmlAttributeNode>
attributes, Token attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Tok
en closingTag, Token nodeEnd, List<EmbeddedExpression> expressions) : super(node
Start, tag, attributes, attributeEnd, tagNodes, contentEnd, closingTag, nodeEnd)
{ |
| 190 this._expressions = expressions; |
| 191 } |
| 192 |
| 193 List<EmbeddedExpression> get expressions => _expressions; |
| 194 } |
| 195 |
| 196 /** |
| 124 * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that wi
ll recursively | 197 * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that wi
ll recursively |
| 125 * visit all of the nodes in an XML structure. For example, using an instance of
this class to visit | 198 * visit all of the nodes in an XML structure. For example, using an instance of
this class to visit |
| 126 * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and | 199 * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and |
| 127 * [XmlTagNode]s to be visited. | 200 * [XmlTagNode]s to be visited. |
| 128 * | 201 * |
| 129 * Subclasses that override a visit method must either invoke the overridden vis
it method or must | 202 * Subclasses that override a visit method must either invoke the overridden vis
it method or must |
| 130 * explicitly ask the visited node to visit its children. Failure to do so will
cause the children | 203 * explicitly ask the visited node to visit its children. Failure to do so will
cause the children |
| 131 * of the visited node to not be visited. | 204 * of the visited node to not be visited. |
| 132 * | 205 * |
| 133 * @coverage dart.engine.html | 206 * @coverage dart.engine.html |
| 134 */ | 207 */ |
| 135 class RecursiveXmlVisitor<R> implements XmlVisitor<R> { | 208 class RecursiveXmlVisitor<R> implements XmlVisitor<R> { |
| 209 R visitHtmlScriptTagNode(HtmlScriptTagNode node) { |
| 210 node.visitChildren(this); |
| 211 return null; |
| 212 } |
| 213 |
| 136 R visitHtmlUnit(HtmlUnit node) { | 214 R visitHtmlUnit(HtmlUnit node) { |
| 137 node.visitChildren(this); | 215 node.visitChildren(this); |
| 138 return null; | 216 return null; |
| 139 } | 217 } |
| 140 | 218 |
| 141 R visitXmlAttributeNode(XmlAttributeNode node) { | 219 R visitXmlAttributeNode(XmlAttributeNode node) { |
| 142 node.visitChildren(this); | 220 node.visitChildren(this); |
| 143 return null; | 221 return null; |
| 144 } | 222 } |
| 145 | 223 |
| 146 R visitXmlTagNode(XmlTagNode node) { | 224 R visitXmlTagNode(XmlTagNode node) { |
| 147 node.visitChildren(this); | 225 node.visitChildren(this); |
| 148 return null; | 226 return null; |
| 149 } | 227 } |
| 150 } | 228 } |
| 151 | 229 |
| 152 /** | 230 /** |
| 231 * Instances of the class `HtmlScriptTagNode` represent a script tag within an H
TML file that |
| 232 * references a Dart script. |
| 233 */ |
| 234 class HtmlScriptTagNode extends XmlTagNode { |
| 235 /** |
| 236 * The AST structure representing the Dart code within this tag. |
| 237 */ |
| 238 CompilationUnit _script; |
| 239 |
| 240 /** |
| 241 * The element representing this script. |
| 242 */ |
| 243 HtmlScriptElement scriptElement; |
| 244 |
| 245 /** |
| 246 * Initialize a newly created node to represent a script tag within an HTML fi
le that references a |
| 247 * Dart script. |
| 248 * |
| 249 * @param nodeStart the token marking the beginning of the tag |
| 250 * @param tag the name of the tag |
| 251 * @param attributes the attributes in the tag |
| 252 * @param attributeEnd the token terminating the region where attributes can b
e |
| 253 * @param tagNodes the children of the tag |
| 254 * @param contentEnd the token that starts the closing tag |
| 255 * @param closingTag the name of the tag that occurs in the closing tag |
| 256 * @param nodeEnd the last token in the tag |
| 257 */ |
| 258 HtmlScriptTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> attribute
s, Token attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closin
gTag, Token nodeEnd) : super(nodeStart, tag, attributes, attributeEnd, tagNodes,
contentEnd, closingTag, nodeEnd); |
| 259 |
| 260 accept(XmlVisitor visitor) => visitor.visitHtmlScriptTagNode(this); |
| 261 |
| 262 /** |
| 263 * Return the AST structure representing the Dart code within this tag, or `nu
ll` if this |
| 264 * tag references an external script. |
| 265 * |
| 266 * @return the AST structure representing the Dart code within this tag |
| 267 */ |
| 268 CompilationUnit get script => _script; |
| 269 |
| 270 /** |
| 271 * Set the AST structure representing the Dart code within this tag to the giv
en compilation unit. |
| 272 * |
| 273 * @param unit the AST structure representing the Dart code within this tag |
| 274 */ |
| 275 void set script(CompilationUnit unit) { |
| 276 _script = unit; |
| 277 } |
| 278 } |
| 279 |
| 280 /** |
| 153 * The abstract class `XmlNode` defines behavior common to all XML/HTML nodes. | 281 * The abstract class `XmlNode` defines behavior common to all XML/HTML nodes. |
| 154 * | 282 * |
| 155 * @coverage dart.engine.html | 283 * @coverage dart.engine.html |
| 156 */ | 284 */ |
| 157 abstract class XmlNode { | 285 abstract class XmlNode { |
| 158 /** | 286 /** |
| 159 * The parent of the node, or `null` if the node is the root of an AST structu
re. | 287 * The parent of the node, or `null` if the node is the root of an AST structu
re. |
| 160 */ | 288 */ |
| 161 XmlNode _parent; | 289 XmlNode _parent; |
| 162 | 290 |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 AnalysisEngine.instance.logger.logError3(new IllegalArgumentException(bu
ildRecursiveStructureMessage(newParent))); | 451 AnalysisEngine.instance.logger.logError3(new IllegalArgumentException(bu
ildRecursiveStructureMessage(newParent))); |
| 324 return; | 452 return; |
| 325 } | 453 } |
| 326 current = current.parent; | 454 current = current.parent; |
| 327 } | 455 } |
| 328 _parent = newParent; | 456 _parent = newParent; |
| 329 } | 457 } |
| 330 } | 458 } |
| 331 | 459 |
| 332 /** | 460 /** |
| 461 * Instances of the class `AttributeWithEmbeddedExpressions` represent an attrib
ute whose |
| 462 * value contains one or more embedded expressions. |
| 463 */ |
| 464 class AttributeWithEmbeddedExpressions extends XmlAttributeNode { |
| 465 /** |
| 466 * The expressions that are embedded in the attribute's value. |
| 467 */ |
| 468 List<EmbeddedExpression> _expressions; |
| 469 |
| 470 /** |
| 471 * Initialize a newly created attribute whose value contains one or more embed
ded expressions. |
| 472 * |
| 473 * @param name the name of the attribute |
| 474 * @param equals the equals sign separating the name from the value |
| 475 * @param value the value of the attribute |
| 476 * @param expressions the expressions that are embedded in the value |
| 477 */ |
| 478 AttributeWithEmbeddedExpressions(Token name, Token equals, Token value, List<E
mbeddedExpression> expressions) : super(name, equals, value) { |
| 479 this._expressions = expressions; |
| 480 } |
| 481 |
| 482 List<EmbeddedExpression> get expressions => _expressions; |
| 483 } |
| 484 |
| 485 /** |
| 333 * Instances of the class `SimpleXmlVisitor` implement an AST visitor that will
do nothing | 486 * Instances of the class `SimpleXmlVisitor` implement an AST visitor that will
do nothing |
| 334 * when visiting an AST node. It is intended to be a superclass for classes that
use the visitor | 487 * when visiting an AST node. It is intended to be a superclass for classes that
use the visitor |
| 335 * pattern primarily as a dispatch mechanism (and hence don't need to recursivel
y visit a whole | 488 * pattern primarily as a dispatch mechanism (and hence don't need to recursivel
y visit a whole |
| 336 * structure) and that only need to visit a small number of node types. | 489 * structure) and that only need to visit a small number of node types. |
| 337 */ | 490 */ |
| 338 class SimpleXmlVisitor<R> implements XmlVisitor<R> { | 491 class SimpleXmlVisitor<R> implements XmlVisitor<R> { |
| 492 R visitHtmlScriptTagNode(HtmlScriptTagNode node) => null; |
| 493 |
| 339 R visitHtmlUnit(HtmlUnit htmlUnit) => null; | 494 R visitHtmlUnit(HtmlUnit htmlUnit) => null; |
| 340 | 495 |
| 341 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode) => null; | 496 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode) => null; |
| 342 | 497 |
| 343 R visitXmlTagNode(XmlTagNode xmlTagNode) => null; | 498 R visitXmlTagNode(XmlTagNode xmlTagNode) => null; |
| 344 } | 499 } |
| 345 | 500 |
| 346 /** | 501 /** |
| 347 * The abstract class `AbstractScanner` implements a scanner for HTML code. Subc
lasses are | 502 * The abstract class `AbstractScanner` implements a scanner for HTML code. Subc
lasses are |
| 348 * required to implement the interface used to access the characters being scann
ed. | 503 * required to implement the interface used to access the characters being scann
ed. |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 /** | 962 /** |
| 808 * Initialize a newly created visitor to write source code representing the vi
sited nodes to the | 963 * Initialize a newly created visitor to write source code representing the vi
sited nodes to the |
| 809 * given writer. | 964 * given writer. |
| 810 * | 965 * |
| 811 * @param writer the writer to which the source is to be written | 966 * @param writer the writer to which the source is to be written |
| 812 */ | 967 */ |
| 813 ToSourceVisitor(PrintWriter writer) { | 968 ToSourceVisitor(PrintWriter writer) { |
| 814 this._writer = writer; | 969 this._writer = writer; |
| 815 } | 970 } |
| 816 | 971 |
| 972 Object visitHtmlScriptTagNode(HtmlScriptTagNode node) => visitXmlTagNode(node)
; |
| 973 |
| 817 Object visitHtmlUnit(HtmlUnit node) { | 974 Object visitHtmlUnit(HtmlUnit node) { |
| 818 for (XmlTagNode child in node.tagNodes) { | 975 for (XmlTagNode child in node.tagNodes) { |
| 819 visit(child); | 976 visit(child); |
| 820 } | 977 } |
| 821 return null; | 978 return null; |
| 822 } | 979 } |
| 823 | 980 |
| 824 Object visitXmlAttributeNode(XmlAttributeNode node) { | 981 Object visitXmlAttributeNode(XmlAttributeNode node) { |
| 825 String name = node.name.lexeme; | 982 String name = node.name.lexeme; |
| 826 Token value = node.value; | 983 Token value = node.value; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 this.value = value; | 1118 this.value = value; |
| 962 } | 1119 } |
| 963 | 1120 |
| 964 accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this); | 1121 accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this); |
| 965 | 1122 |
| 966 Token get beginToken => name; | 1123 Token get beginToken => name; |
| 967 | 1124 |
| 968 Token get endToken => value; | 1125 Token get endToken => value; |
| 969 | 1126 |
| 970 /** | 1127 /** |
| 1128 * Return the expressions that are embedded in the attribute's value. |
| 1129 * |
| 1130 * @return the expressions that are embedded in the attribute's value |
| 1131 */ |
| 1132 List<EmbeddedExpression> get expressions => EmbeddedExpression.EMPTY_ARRAY; |
| 1133 |
| 1134 /** |
| 971 * Answer the lexeme for the value token without the leading and trailing quot
es. | 1135 * Answer the lexeme for the value token without the leading and trailing quot
es. |
| 972 * | 1136 * |
| 973 * @return the text or `null` if the value is not specified | 1137 * @return the text or `null` if the value is not specified |
| 974 */ | 1138 */ |
| 975 String get text { | 1139 String get text { |
| 976 if (value == null) { | 1140 if (value == null) { |
| 977 return null; | 1141 return null; |
| 978 } | 1142 } |
| 979 String text = value.lexeme; | 1143 String text = value.lexeme; |
| 980 int len = text.length; | 1144 int len = text.length; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 994 } | 1158 } |
| 995 } | 1159 } |
| 996 return text; | 1160 return text; |
| 997 } | 1161 } |
| 998 | 1162 |
| 999 void visitChildren(XmlVisitor visitor) { | 1163 void visitChildren(XmlVisitor visitor) { |
| 1000 } | 1164 } |
| 1001 } | 1165 } |
| 1002 | 1166 |
| 1003 /** | 1167 /** |
| 1168 * Instances of the class `EmbeddedDartVisitor` implement a recursive visitor fo
r HTML files |
| 1169 * that will invoke another visitor on all embedded dart scripts and expressions
. |
| 1170 */ |
| 1171 class EmbeddedDartVisitor<R> implements XmlVisitor<R> { |
| 1172 /** |
| 1173 * The visitor used to visit embedded Dart code. |
| 1174 */ |
| 1175 ASTVisitor<R> _dartVisitor; |
| 1176 |
| 1177 /** |
| 1178 * Initialize a newly created visitor to visit all of the nodes in an HTML str
ucture and to use |
| 1179 * the given visitor to visit all of the nodes representing any embedded scrip
ts or expressions. |
| 1180 * |
| 1181 * @param dartVisitor the visitor used to visit embedded Dart code |
| 1182 */ |
| 1183 EmbeddedDartVisitor(ASTVisitor<R> dartVisitor) { |
| 1184 this._dartVisitor = dartVisitor; |
| 1185 } |
| 1186 |
| 1187 R visitHtmlScriptTagNode(HtmlScriptTagNode node) { |
| 1188 node.visitChildren(this); |
| 1189 CompilationUnit script = node.script; |
| 1190 if (script != null) { |
| 1191 script.accept(_dartVisitor); |
| 1192 } |
| 1193 return null; |
| 1194 } |
| 1195 |
| 1196 R visitHtmlUnit(HtmlUnit node) { |
| 1197 node.visitChildren(this); |
| 1198 return null; |
| 1199 } |
| 1200 |
| 1201 R visitXmlAttributeNode(XmlAttributeNode node) { |
| 1202 node.visitChildren(this); |
| 1203 for (EmbeddedExpression expression in node.expressions) { |
| 1204 expression.expression.accept(_dartVisitor); |
| 1205 } |
| 1206 return null; |
| 1207 } |
| 1208 |
| 1209 R visitXmlTagNode(XmlTagNode node) { |
| 1210 node.visitChildren(this); |
| 1211 for (EmbeddedExpression expression in node.expressions) { |
| 1212 expression.expression.accept(_dartVisitor); |
| 1213 } |
| 1214 return null; |
| 1215 } |
| 1216 } |
| 1217 |
| 1218 /** |
| 1004 * The interface `XmlVisitor` defines the behavior of objects that can be used t
o visit an | 1219 * The interface `XmlVisitor` defines the behavior of objects that can be used t
o visit an |
| 1005 * [XmlNode] structure. | 1220 * [XmlNode] structure. |
| 1006 * | 1221 * |
| 1007 * @coverage dart.engine.html | 1222 * @coverage dart.engine.html |
| 1008 */ | 1223 */ |
| 1009 abstract class XmlVisitor<R> { | 1224 abstract class XmlVisitor<R> { |
| 1225 R visitHtmlScriptTagNode(HtmlScriptTagNode node); |
| 1226 |
| 1010 R visitHtmlUnit(HtmlUnit htmlUnit); | 1227 R visitHtmlUnit(HtmlUnit htmlUnit); |
| 1011 | 1228 |
| 1012 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode); | 1229 R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode); |
| 1013 | 1230 |
| 1014 R visitXmlTagNode(XmlTagNode xmlTagNode); | 1231 R visitXmlTagNode(XmlTagNode xmlTagNode); |
| 1015 } | 1232 } |
| 1016 | 1233 |
| 1017 /** | 1234 /** |
| 1018 * Instances of `HtmlScanner` receive and scan HTML content from a [Source].<br/
> | 1235 * Instances of `HtmlScanner` receive and scan HTML content from a [Source].<br/
> |
| 1019 * For example, the following code scans HTML source and returns the result: | 1236 * For example, the following code scans HTML source and returns the result: |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 /** | 1317 /** |
| 1101 * Construct a parser for the specified source. | 1318 * Construct a parser for the specified source. |
| 1102 * | 1319 * |
| 1103 * @param source the source being parsed | 1320 * @param source the source being parsed |
| 1104 */ | 1321 */ |
| 1105 XmlParser(Source source) { | 1322 XmlParser(Source source) { |
| 1106 this.source = source; | 1323 this.source = source; |
| 1107 } | 1324 } |
| 1108 | 1325 |
| 1109 /** | 1326 /** |
| 1327 * Create a node representing an attribute. |
| 1328 * |
| 1329 * @param name the name of the attribute |
| 1330 * @param equals the equals sign, or `null` if there is no value |
| 1331 * @param value the value of the attribute |
| 1332 * @return the node that was created |
| 1333 */ |
| 1334 XmlAttributeNode createAttributeNode(Token name, Token equals, Token value) =>
new XmlAttributeNode(name, equals, value); |
| 1335 |
| 1336 /** |
| 1337 * Create a node representing a tag. |
| 1338 * |
| 1339 * @param nodeStart the token marking the beginning of the tag |
| 1340 * @param tag the name of the tag |
| 1341 * @param attributes the attributes in the tag |
| 1342 * @param attributeEnd the token terminating the region where attributes can b
e |
| 1343 * @param tagNodes the children of the tag |
| 1344 * @param contentEnd the token that starts the closing tag |
| 1345 * @param closingTag the name of the tag that occurs in the closing tag |
| 1346 * @param nodeEnd the last token in the tag |
| 1347 * @return the node that was created |
| 1348 */ |
| 1349 XmlTagNode createTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> at
tributes, Token attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token
closingTag, Token nodeEnd) => new XmlTagNode(nodeStart, tag, attributes, attrib
uteEnd, tagNodes, contentEnd, closingTag, nodeEnd); |
| 1350 |
| 1351 /** |
| 1110 * Answer `true` if the specified tag is self closing and thus should never ha
ve content or | 1352 * Answer `true` if the specified tag is self closing and thus should never ha
ve content or |
| 1111 * child tag nodes. | 1353 * child tag nodes. |
| 1112 * | 1354 * |
| 1113 * @param tag the tag (not `null`) | 1355 * @param tag the tag (not `null`) |
| 1114 * @return `true` if self closing | 1356 * @return `true` if self closing |
| 1115 */ | 1357 */ |
| 1116 bool isSelfClosing(Token tag) => false; | 1358 bool isSelfClosing(Token tag) => false; |
| 1117 | 1359 |
| 1118 /** | 1360 /** |
| 1119 * Parse the entire token stream and in the process, advance the current token
to the end of the | 1361 * Parse the entire token stream and in the process, advance the current token
to the end of the |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 equals = insertSyntheticToken(TokenType.EQ); | 1414 equals = insertSyntheticToken(TokenType.EQ); |
| 1173 } | 1415 } |
| 1174 Token value; | 1416 Token value; |
| 1175 if (identical(currentToken.type, TokenType.STRING)) { | 1417 if (identical(currentToken.type, TokenType.STRING)) { |
| 1176 value = currentToken; | 1418 value = currentToken; |
| 1177 currentToken = currentToken.next; | 1419 currentToken = currentToken.next; |
| 1178 } else { | 1420 } else { |
| 1179 reportUnexpectedToken(); | 1421 reportUnexpectedToken(); |
| 1180 value = insertSyntheticToken(TokenType.STRING); | 1422 value = insertSyntheticToken(TokenType.STRING); |
| 1181 } | 1423 } |
| 1182 return new XmlAttributeNode(name, equals, value); | 1424 return createAttributeNode(name, equals, value); |
| 1183 } | 1425 } |
| 1184 | 1426 |
| 1185 /** | 1427 /** |
| 1186 * Parse the stream for a sequence of attributes. This method advances the cur
rent token to the | 1428 * Parse the stream for a sequence of attributes. This method advances the cur
rent token to the |
| 1187 * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF]. | 1429 * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF]. |
| 1188 * | 1430 * |
| 1189 * @return a collection of zero or more attributes (not `null`, contains no `n
ull`s) | 1431 * @return a collection of zero or more attributes (not `null`, contains no `n
ull`s) |
| 1190 */ | 1432 */ |
| 1191 List<XmlAttributeNode> parseAttributes() { | 1433 List<XmlAttributeNode> parseAttributes() { |
| 1192 TokenType type = currentToken.type; | 1434 TokenType type = currentToken.type; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 List<XmlAttributeNode> attributes = parseAttributes(); | 1500 List<XmlAttributeNode> attributes = parseAttributes(); |
| 1259 Token attributeEnd; | 1501 Token attributeEnd; |
| 1260 if (identical(currentToken.type, TokenType.GT) || identical(currentToken.typ
e, TokenType.SLASH_GT)) { | 1502 if (identical(currentToken.type, TokenType.GT) || identical(currentToken.typ
e, TokenType.SLASH_GT)) { |
| 1261 attributeEnd = currentToken; | 1503 attributeEnd = currentToken; |
| 1262 currentToken = currentToken.next; | 1504 currentToken = currentToken.next; |
| 1263 } else { | 1505 } else { |
| 1264 reportUnexpectedToken(); | 1506 reportUnexpectedToken(); |
| 1265 attributeEnd = insertSyntheticToken(TokenType.SLASH_GT); | 1507 attributeEnd = insertSyntheticToken(TokenType.SLASH_GT); |
| 1266 } | 1508 } |
| 1267 if (identical(attributeEnd.type, TokenType.SLASH_GT) || isSelfClosing(tag))
{ | 1509 if (identical(attributeEnd.type, TokenType.SLASH_GT) || isSelfClosing(tag))
{ |
| 1268 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, XmlTagNode
.NO_TAG_NODES, currentToken, null, attributeEnd); | 1510 return createTagNode(nodeStart, tag, attributes, attributeEnd, XmlTagNode.
NO_TAG_NODES, currentToken, null, attributeEnd); |
| 1269 } | 1511 } |
| 1270 List<XmlTagNode> tagNodes = parseChildTagNodes(); | 1512 List<XmlTagNode> tagNodes = parseChildTagNodes(); |
| 1271 Token contentEnd; | 1513 Token contentEnd; |
| 1272 if (identical(currentToken.type, TokenType.LT_SLASH)) { | 1514 if (identical(currentToken.type, TokenType.LT_SLASH)) { |
| 1273 contentEnd = currentToken; | 1515 contentEnd = currentToken; |
| 1274 currentToken = currentToken.next; | 1516 currentToken = currentToken.next; |
| 1275 } else { | 1517 } else { |
| 1276 reportUnexpectedToken(); | 1518 reportUnexpectedToken(); |
| 1277 contentEnd = insertSyntheticToken(TokenType.LT_SLASH); | 1519 contentEnd = insertSyntheticToken(TokenType.LT_SLASH); |
| 1278 } | 1520 } |
| 1279 Token closingTag; | 1521 Token closingTag; |
| 1280 if (identical(currentToken.type, TokenType.TAG)) { | 1522 if (identical(currentToken.type, TokenType.TAG)) { |
| 1281 closingTag = currentToken; | 1523 closingTag = currentToken; |
| 1282 currentToken = currentToken.next; | 1524 currentToken = currentToken.next; |
| 1283 } else { | 1525 } else { |
| 1284 reportUnexpectedToken(); | 1526 reportUnexpectedToken(); |
| 1285 closingTag = insertSyntheticToken(TokenType.TAG); | 1527 closingTag = insertSyntheticToken(TokenType.TAG); |
| 1286 } | 1528 } |
| 1287 Token nodeEnd; | 1529 Token nodeEnd; |
| 1288 if (identical(currentToken.type, TokenType.GT)) { | 1530 if (identical(currentToken.type, TokenType.GT)) { |
| 1289 nodeEnd = currentToken; | 1531 nodeEnd = currentToken; |
| 1290 currentToken = currentToken.next; | 1532 currentToken = currentToken.next; |
| 1291 } else { | 1533 } else { |
| 1292 reportUnexpectedToken(); | 1534 reportUnexpectedToken(); |
| 1293 nodeEnd = insertSyntheticToken(TokenType.GT); | 1535 nodeEnd = insertSyntheticToken(TokenType.GT); |
| 1294 } | 1536 } |
| 1295 return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes, co
ntentEnd, closingTag, nodeEnd); | 1537 return createTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes, con
tentEnd, closingTag, nodeEnd); |
| 1296 } | 1538 } |
| 1297 | 1539 |
| 1298 /** | 1540 /** |
| 1299 * Report the current token as unexpected | 1541 * Report the current token as unexpected |
| 1300 */ | 1542 */ |
| 1301 void reportUnexpectedToken() { | 1543 void reportUnexpectedToken() { |
| 1302 } | 1544 } |
| 1303 } | 1545 } |
| 1304 | 1546 |
| 1305 /** | 1547 /** |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 } | 1721 } |
| 1480 if (attributeEnd != null) { | 1722 if (attributeEnd != null) { |
| 1481 return attributeEnd; | 1723 return attributeEnd; |
| 1482 } | 1724 } |
| 1483 if (!attributes.isEmpty) { | 1725 if (!attributes.isEmpty) { |
| 1484 return attributes[attributes.length - 1].endToken; | 1726 return attributes[attributes.length - 1].endToken; |
| 1485 } | 1727 } |
| 1486 return tag; | 1728 return tag; |
| 1487 } | 1729 } |
| 1488 | 1730 |
| 1731 /** |
| 1732 * Return the expressions that are embedded in the tag's content. |
| 1733 * |
| 1734 * @return the expressions that are embedded in the tag's content |
| 1735 */ |
| 1736 List<EmbeddedExpression> get expressions => EmbeddedExpression.EMPTY_ARRAY; |
| 1737 |
| 1489 void visitChildren(XmlVisitor visitor) { | 1738 void visitChildren(XmlVisitor visitor) { |
| 1490 for (XmlAttributeNode node in attributes) { | 1739 for (XmlAttributeNode node in attributes) { |
| 1491 node.accept(visitor); | 1740 node.accept(visitor); |
| 1492 } | 1741 } |
| 1493 for (XmlTagNode node in tagNodes) { | 1742 for (XmlTagNode node in tagNodes) { |
| 1494 node.accept(visitor); | 1743 node.accept(visitor); |
| 1495 } | 1744 } |
| 1496 } | 1745 } |
| 1497 | 1746 |
| 1498 /** | 1747 /** |
| 1499 * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empt
y | 1748 * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empt
y |
| 1500 */ | 1749 */ |
| 1501 List becomeParentOfEmpty(List children, List ifEmpty) { | 1750 List becomeParentOfEmpty(List children, List ifEmpty) { |
| 1502 if (children != null && children.isEmpty) { | 1751 if (children != null && children.isEmpty) { |
| 1503 return ifEmpty; | 1752 return ifEmpty; |
| 1504 } | 1753 } |
| 1505 return becomeParentOf(children); | 1754 return becomeParentOf(children); |
| 1506 } | 1755 } |
| 1507 } | 1756 } |
| 1508 | 1757 |
| 1509 /** | 1758 /** |
| 1510 * Instances of the class `HtmlParser` are used to parse tokens into a AST struc
ture comprised | 1759 * Instances of the class `HtmlParser` are used to parse tokens into a AST struc
ture comprised |
| 1511 * of [XmlNode]s. | 1760 * of [XmlNode]s. |
| 1512 * | 1761 * |
| 1513 * @coverage dart.engine.html | 1762 * @coverage dart.engine.html |
| 1514 */ | 1763 */ |
| 1515 class HtmlParser extends XmlParser { | 1764 class HtmlParser extends XmlParser { |
| 1765 /** |
| 1766 * The line information associated with the source being parsed. |
| 1767 */ |
| 1768 LineInfo _lineInfo; |
| 1769 |
| 1770 /** |
| 1771 * The error listener to which errors will be reported. |
| 1772 */ |
| 1773 AnalysisErrorListener _errorListener; |
| 1774 |
| 1775 static String _APPLICATION_DART_IN_DOUBLE_QUOTES = "\"application/dart\""; |
| 1776 |
| 1777 static String _APPLICATION_DART_IN_SINGLE_QUOTES = "'application/dart'"; |
| 1778 |
| 1779 static String _OPENING_DELIMITER = "{{"; |
| 1780 |
| 1781 static String _CLOSING_DELIMITER = "}}"; |
| 1782 |
| 1783 static String _SCRIPT = "script"; |
| 1784 |
| 1785 static String _TYPE = "type"; |
| 1786 |
| 1787 /** |
| 1788 * A set containing the names of tags that do not have a closing tag. |
| 1789 */ |
| 1516 static Set<String> SELF_CLOSING = new Set<String>(); | 1790 static Set<String> SELF_CLOSING = new Set<String>(); |
| 1517 | 1791 |
| 1518 /** | 1792 /** |
| 1519 * Construct a parser for the specified source. | 1793 * Construct a parser for the specified source. |
| 1520 * | 1794 * |
| 1521 * @param source the source being parsed | 1795 * @param source the source being parsed |
| 1796 * @param errorListener the error listener to which errors will be reported |
| 1522 */ | 1797 */ |
| 1523 HtmlParser(Source source) : super(source); | 1798 HtmlParser(Source source, AnalysisErrorListener errorListener) : super(source)
{ |
| 1799 this._errorListener = errorListener; |
| 1800 } |
| 1801 |
| 1802 Token getEndToken(Token tag, List<XmlAttributeNode> attributes, Token attribut
eEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag, Token nodeE
nd) { |
| 1803 if (nodeEnd != null) { |
| 1804 return nodeEnd; |
| 1805 } |
| 1806 if (closingTag != null) { |
| 1807 return closingTag; |
| 1808 } |
| 1809 if (contentEnd != null) { |
| 1810 return contentEnd; |
| 1811 } |
| 1812 if (!tagNodes.isEmpty) { |
| 1813 return tagNodes[tagNodes.length - 1].endToken; |
| 1814 } |
| 1815 if (attributeEnd != null) { |
| 1816 return attributeEnd; |
| 1817 } |
| 1818 if (!attributes.isEmpty) { |
| 1819 return attributes[attributes.length - 1].endToken; |
| 1820 } |
| 1821 return tag; |
| 1822 } |
| 1524 | 1823 |
| 1525 /** | 1824 /** |
| 1526 * Parse the tokens specified by the given scan result. | 1825 * Parse the tokens specified by the given scan result. |
| 1527 * | 1826 * |
| 1528 * @param scanResult the result of scanning an HTML source (not `null`) | 1827 * @param scanResult the result of scanning an HTML source (not `null`) |
| 1529 * @return the parse result (not `null`) | 1828 * @return the parse result (not `null`) |
| 1530 */ | 1829 */ |
| 1531 HtmlParseResult parse(HtmlScanResult scanResult) { | 1830 HtmlParseResult parse(HtmlScanResult scanResult) { |
| 1831 List<int> lineStarts = scanResult.lineStarts; |
| 1832 _lineInfo = new LineInfo(lineStarts); |
| 1532 Token firstToken = scanResult.token; | 1833 Token firstToken = scanResult.token; |
| 1533 List<XmlTagNode> tagNodes = parseTopTagNodes(firstToken); | 1834 List<XmlTagNode> tagNodes = parseTopTagNodes(firstToken); |
| 1534 HtmlUnit unit = new HtmlUnit(firstToken, tagNodes, currentToken); | 1835 HtmlUnit unit = new HtmlUnit(firstToken, tagNodes, currentToken); |
| 1535 return new HtmlParseResult(scanResult.modificationTime, firstToken, scanResu
lt.lineStarts, unit); | 1836 return new HtmlParseResult(scanResult.modificationTime, firstToken, scanResu
lt.lineStarts, unit); |
| 1536 } | 1837 } |
| 1537 | 1838 |
| 1538 /** | 1839 /** |
| 1539 * Scan then parse the specified source. | 1840 * Scan then parse the specified source. |
| 1540 * | 1841 * |
| 1541 * @param source the source to be scanned and parsed (not `null`) | 1842 * @param source the source to be scanned and parsed (not `null`) |
| 1542 * @return the parse result (not `null`) | 1843 * @return the parse result (not `null`) |
| 1543 */ | 1844 */ |
| 1544 HtmlParseResult parse2(Source source) { | 1845 HtmlParseResult parse2(Source source) { |
| 1545 HtmlScanner scanner = new HtmlScanner(source); | 1846 HtmlScanner scanner = new HtmlScanner(source); |
| 1546 source.getContents(scanner); | 1847 source.getContents(scanner); |
| 1547 return parse(scanner.result); | 1848 return parse(scanner.result); |
| 1548 } | 1849 } |
| 1549 | 1850 |
| 1851 XmlAttributeNode createAttributeNode(Token name, Token equals, Token value) { |
| 1852 List<EmbeddedExpression> expressions = new List<EmbeddedExpression>(); |
| 1853 addEmbeddedExpressions(expressions, value); |
| 1854 if (expressions.isEmpty) { |
| 1855 return new XmlAttributeNode(name, equals, value); |
| 1856 } |
| 1857 return new AttributeWithEmbeddedExpressions(name, equals, value, new List.fr
om(expressions)); |
| 1858 } |
| 1859 |
| 1860 XmlTagNode createTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> at
tributes, Token attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token
closingTag, Token nodeEnd) { |
| 1861 if (isScriptNode(tag, attributes, tagNodes)) { |
| 1862 HtmlScriptTagNode tagNode = new HtmlScriptTagNode(nodeStart, tag, attribut
es, attributeEnd, tagNodes, contentEnd, closingTag, nodeEnd); |
| 1863 String contents = tagNode.content; |
| 1864 int contentOffset = attributeEnd.end; |
| 1865 LineInfo_Location location = _lineInfo.getLocation(contentOffset); |
| 1866 sc.Scanner scanner = new sc.Scanner(source, new sc.SubSequenceReader(new C
harSequence(contents), contentOffset), _errorListener); |
| 1867 scanner.setSourceStart(location.lineNumber, location.columnNumber); |
| 1868 sc.Token firstToken = scanner.tokenize(); |
| 1869 Parser parser = new Parser(source, _errorListener); |
| 1870 CompilationUnit unit = parser.parseCompilationUnit(firstToken); |
| 1871 unit.lineInfo = _lineInfo; |
| 1872 tagNode.script = unit; |
| 1873 return tagNode; |
| 1874 } |
| 1875 Token token = nodeStart; |
| 1876 Token endToken = getEndToken(tag, attributes, attributeEnd, tagNodes, conten
tEnd, closingTag, nodeEnd); |
| 1877 List<EmbeddedExpression> expressions = new List<EmbeddedExpression>(); |
| 1878 while (token != endToken) { |
| 1879 if (identical(token.type, TokenType.TEXT)) { |
| 1880 addEmbeddedExpressions(expressions, token); |
| 1881 } |
| 1882 token = token.next; |
| 1883 } |
| 1884 if (expressions.isEmpty) { |
| 1885 return super.createTagNode(nodeStart, tag, attributes, attributeEnd, tagNo
des, contentEnd, closingTag, nodeEnd); |
| 1886 } |
| 1887 return new TagWithEmbeddedExpressions(nodeStart, tag, attributes, attributeE
nd, tagNodes, contentEnd, closingTag, nodeEnd, new List.from(expressions)); |
| 1888 } |
| 1889 |
| 1550 bool isSelfClosing(Token tag) => SELF_CLOSING.contains(tag.lexeme); | 1890 bool isSelfClosing(Token tag) => SELF_CLOSING.contains(tag.lexeme); |
| 1891 |
| 1892 /** |
| 1893 * Parse the value of the given token for embedded expressions, and add any em
bedded expressions |
| 1894 * that are found to the given list of expressions. |
| 1895 * |
| 1896 * @param expressions the list to which embedded expressions are to be added |
| 1897 * @param token the token whose value is to be parsed |
| 1898 */ |
| 1899 void addEmbeddedExpressions(List<EmbeddedExpression> expressions, Token token)
{ |
| 1900 String lexeme = token.lexeme; |
| 1901 int startIndex = lexeme.indexOf(_OPENING_DELIMITER); |
| 1902 while (startIndex >= 0) { |
| 1903 int endIndex = JavaString.indexOf(lexeme, _CLOSING_DELIMITER, startIndex +
2); |
| 1904 if (endIndex < 0) { |
| 1905 return; |
| 1906 } else if (startIndex + 2 < endIndex) { |
| 1907 int offset = token.offset; |
| 1908 expressions.add(new EmbeddedExpression(startIndex, parseEmbeddedExpressi
on(lexeme.substring(startIndex + 2, endIndex), offset + startIndex), endIndex)); |
| 1909 } |
| 1910 startIndex = JavaString.indexOf(lexeme, _OPENING_DELIMITER, endIndex + 2); |
| 1911 } |
| 1912 } |
| 1913 |
| 1914 /** |
| 1915 * Determine if the specified node is a Dart script. |
| 1916 * |
| 1917 * @param node the node to be tested (not `null`) |
| 1918 * @return `true` if the node is a Dart script |
| 1919 */ |
| 1920 bool isScriptNode(Token tag, List<XmlAttributeNode> attributes, List<XmlTagNod
e> tagNodes) { |
| 1921 if (tagNodes.length != 0 || tag.lexeme != _SCRIPT) { |
| 1922 return false; |
| 1923 } |
| 1924 for (XmlAttributeNode attribute in attributes) { |
| 1925 if (attribute.name.lexeme == _TYPE) { |
| 1926 Token valueToken = attribute.value; |
| 1927 if (valueToken != null) { |
| 1928 String value = valueToken.lexeme; |
| 1929 if (value == _APPLICATION_DART_IN_DOUBLE_QUOTES || value == _APPLICATI
ON_DART_IN_SINGLE_QUOTES) { |
| 1930 return true; |
| 1931 } |
| 1932 } |
| 1933 } |
| 1934 } |
| 1935 return false; |
| 1936 } |
| 1937 |
| 1938 /** |
| 1939 * Given the contents of an embedded expression that occurs at the given offse
t, parse it as a |
| 1940 * Dart expression. The contents should not include the expression's delimiter
s. |
| 1941 * |
| 1942 * @param contents the contents of the expression |
| 1943 * @param contentOffset the offset of the expression in the larger file |
| 1944 * @return the Dart expression that was parsed |
| 1945 */ |
| 1946 Expression parseEmbeddedExpression(String contents, int contentOffset) { |
| 1947 LineInfo_Location location = _lineInfo.getLocation(contentOffset); |
| 1948 sc.Scanner scanner = new sc.Scanner(source, new sc.SubSequenceReader(new Cha
rSequence(contents), contentOffset), _errorListener); |
| 1949 scanner.setSourceStart(location.lineNumber, location.columnNumber); |
| 1950 sc.Token firstToken = scanner.tokenize(); |
| 1951 Parser parser = new Parser(source, _errorListener); |
| 1952 return parser.parseExpression(firstToken); |
| 1953 } |
| 1551 } | 1954 } |
| 1552 | 1955 |
| 1553 /** | 1956 /** |
| 1554 * Instances of the class `HtmlUnit` represent the contents of an HTML file. | 1957 * Instances of the class `HtmlUnit` represent the contents of an HTML file. |
| 1555 * | 1958 * |
| 1556 * @coverage dart.engine.html | 1959 * @coverage dart.engine.html |
| 1557 */ | 1960 */ |
| 1558 class HtmlUnit extends XmlNode { | 1961 class HtmlUnit extends XmlNode { |
| 1559 /** | 1962 /** |
| 1560 * The first token in the token stream that was parsed to form this HTML unit. | 1963 * The first token in the token stream that was parsed to form this HTML unit. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1596 Token get beginToken => _beginToken; | 1999 Token get beginToken => _beginToken; |
| 1597 | 2000 |
| 1598 Token get endToken => _endToken; | 2001 Token get endToken => _endToken; |
| 1599 | 2002 |
| 1600 void visitChildren(XmlVisitor visitor) { | 2003 void visitChildren(XmlVisitor visitor) { |
| 1601 for (XmlTagNode node in tagNodes) { | 2004 for (XmlTagNode node in tagNodes) { |
| 1602 node.accept(visitor); | 2005 node.accept(visitor); |
| 1603 } | 2006 } |
| 1604 } | 2007 } |
| 1605 } | 2008 } |
| OLD | NEW |