Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: frog/leg/tree/nodes.dart

Issue 9642001: Make string juxtaposition combine properly with string interpolations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix typo Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 interface Visitor<R> { 5 interface Visitor<R> {
6 R visitBlock(Block node); 6 R visitBlock(Block node);
7 R visitBreakStatement(BreakStatement node); 7 R visitBreakStatement(BreakStatement node);
8 R visitCatchBlock(CatchBlock node); 8 R visitCatchBlock(CatchBlock node);
9 R visitClassNode(ClassNode node); 9 R visitClassNode(ClassNode node);
10 R visitConditional(Conditional node); 10 R visitConditional(Conditional node);
11 R visitContinueStatement(ContinueStatement node); 11 R visitContinueStatement(ContinueStatement node);
12 R visitDoWhile(DoWhile node); 12 R visitDoWhile(DoWhile node);
13 R visitEmptyStatement(EmptyStatement node); 13 R visitEmptyStatement(EmptyStatement node);
14 R visitExpressionStatement(ExpressionStatement node); 14 R visitExpressionStatement(ExpressionStatement node);
15 R visitFor(For node); 15 R visitFor(For node);
16 R visitForInStatement(ForInStatement node); 16 R visitForInStatement(ForInStatement node);
17 R visitFunctionDeclaration(FunctionDeclaration node); 17 R visitFunctionDeclaration(FunctionDeclaration node);
18 R visitFunctionExpression(FunctionExpression node); 18 R visitFunctionExpression(FunctionExpression node);
19 R visitIdentifier(Identifier node); 19 R visitIdentifier(Identifier node);
20 R visitIf(If node); 20 R visitIf(If node);
21 R visitLabeledStatement(LabeledStatement node); 21 R visitLabeledStatement(LabeledStatement node);
22 R visitLiteralBool(LiteralBool node); 22 R visitLiteralBool(LiteralBool node);
23 R visitLiteralDouble(LiteralDouble node); 23 R visitLiteralDouble(LiteralDouble node);
24 R visitLiteralInt(LiteralInt node); 24 R visitLiteralInt(LiteralInt node);
25 R visitLiteralList(LiteralList node); 25 R visitLiteralList(LiteralList node);
26 R visitLiteralMap(LiteralMap node); 26 R visitLiteralMap(LiteralMap node);
27 R visitLiteralMapEntry(LiteralMapEntry node); 27 R visitLiteralMapEntry(LiteralMapEntry node);
28 R visitLiteralNull(LiteralNull node); 28 R visitLiteralNull(LiteralNull node);
29 R visitLiteralString(LiteralString node); 29 R visitLiteralString(LiteralString node);
30 R visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node); 30 R visitStringJuxtaposition(StringJuxtaposition node);
31 R visitModifiers(Modifiers node); 31 R visitModifiers(Modifiers node);
32 R visitNamedArgument(NamedArgument node); 32 R visitNamedArgument(NamedArgument node);
33 R visitNewExpression(NewExpression node); 33 R visitNewExpression(NewExpression node);
34 R visitNodeList(NodeList node); 34 R visitNodeList(NodeList node);
35 R visitOperator(Operator node); 35 R visitOperator(Operator node);
36 R visitParenthesizedExpression(ParenthesizedExpression node); 36 R visitParenthesizedExpression(ParenthesizedExpression node);
37 R visitReturn(Return node); 37 R visitReturn(Return node);
38 R visitScriptTag(ScriptTag node); 38 R visitScriptTag(ScriptTag node);
39 R visitSend(Send node); 39 R visitSend(Send node);
40 R visitSendSet(SendSet node); 40 R visitSendSet(SendSet node);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 NodeList asNodeList() => null; 130 NodeList asNodeList() => null;
131 Operator asOperator() => null; 131 Operator asOperator() => null;
132 ParenthesizedExpression asParenthesizedExpression() => null; 132 ParenthesizedExpression asParenthesizedExpression() => null;
133 Return asReturn() => null; 133 Return asReturn() => null;
134 ScriptTag asScriptTag() => null; 134 ScriptTag asScriptTag() => null;
135 Send asSend() => null; 135 Send asSend() => null;
136 SendSet asSendSet() => null; 136 SendSet asSendSet() => null;
137 Statement asStatement() => null; 137 Statement asStatement() => null;
138 StringInterpolation asStringInterpolation() => null; 138 StringInterpolation asStringInterpolation() => null;
139 StringInterpolationPart asStringInterpolationPart() => null; 139 StringInterpolationPart asStringInterpolationPart() => null;
140 StringJuxtaposition asStringJuxtaposition() => null;
140 SwitchCase asSwitchCase() => null; 141 SwitchCase asSwitchCase() => null;
141 SwitchStatement asSwitchStatement() => null; 142 SwitchStatement asSwitchStatement() => null;
142 Throw asThrow() => null; 143 Throw asThrow() => null;
143 TryStatement asTryStatement() => null; 144 TryStatement asTryStatement() => null;
144 TypeAnnotation asTypeAnnotation() => null; 145 TypeAnnotation asTypeAnnotation() => null;
145 Typedef asTypedef() => null; 146 Typedef asTypedef() => null;
146 TypeVariable asTypeVariable() => null; 147 TypeVariable asTypeVariable() => null;
147 VariableDefinitions asVariableDefinitions() => null; 148 VariableDefinitions asVariableDefinitions() => null;
148 While asWhile() => null; 149 While asWhile() => null;
149 150
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 725
725 int get leftQuoteLength() => (raw ? 1 : 0) + leftQuoteCharCount; 726 int get leftQuoteLength() => (raw ? 1 : 0) + leftQuoteCharCount;
726 int get rightQuoteLength() => (leftQuoteCharCount > 2) ? 3 : 1; 727 int get rightQuoteLength() => (leftQuoteCharCount > 2) ? 3 : 1;
727 static StringQuoting getQuoting(int quote, bool raw, int quoteLength) { 728 static StringQuoting getQuoting(int quote, bool raw, int quoteLength) {
728 int index = quoteLength - 1; 729 int index = quoteLength - 1;
729 if (quoteLength > 2) index -= 1; 730 if (quoteLength > 2) index -= 1;
730 return mapping[(raw ? 1 : 0) + index * 2 + (quote === $SQ ? 8 : 0)]; 731 return mapping[(raw ? 1 : 0) + index * 2 + (quote === $SQ ? 8 : 0)];
731 } 732 }
732 } 733 }
733 734
734 class DartString implements Iterable<int> {
735 // This is a convenience constructor. If you need a const literal DartString,
736 // use [const LiteralDartString(string)] directly.
737 factory DartString.literal(String string) => new LiteralDartString(string);
738 factory DartString.rawString(SourceString source, int length) =>
739 new RawSourceDartString(source, length);
740 factory DartString.escapedString(SourceString source, int length) =>
741 new EscapedSourceDartString(source, length);
742 const DartString();
743 abstract int get length();
744 bool isEmpty() => length == 0;
745 abstract Iterator<int> iterator();
746 abstract String slowToString();
747
748 bool operator ==(var other) {
749 if (other is !DartString) return false;
750 DartString otherString = other;
751 if (length != otherString.length) return false;
752 Iterator it1 = iterator();
753 Iterator it2 = otherString.iterator();
754 while (it1.hasNext()) {
755 if (it1.next() != it2.next()) return false;
756 }
757 return true;
758 }
759 String toString() => "DartString#${length}:${slowToString()}";
760 abstract SourceString get source();
761 }
762
763 class LiteralDartString extends DartString {
764 final String string;
765 const LiteralDartString(this.string);
766 int get length() => string.length;
767 Iterator<int> iterator() => new StringCodeIterator(string);
768 String slowToString() => string;
769 SourceString get source() => new StringWrapper(string);
770 }
771
772 class SourceBasedDartString extends DartString {
773 String toStringCache = null;
774 final SourceString source;
775 final int length;
776 SourceBasedDartString(this.source, this.length);
777 abstract Iterator<int> iterator();
778 }
779
780 class RawSourceDartString extends SourceBasedDartString {
781 RawSourceDartString(source, length) : super(source, length);
782 Iterator<int> iterator() => source.iterator();
783 String slowToString() {
784 if (toStringCache !== null) return toStringCache;
785 toStringCache = source.slowToString();
786 return toStringCache;
787 }
788 }
789
790 class EscapedSourceDartString extends SourceBasedDartString {
791 EscapedSourceDartString(source, length) : super(source, length);
792 Iterator<int> iterator() {
793 if (toStringCache !== null) return new StringCodeIterator(toStringCache);
794 return new StringEscapeIterator(source);
795 }
796 String slowToString() {
797 if (toStringCache !== null) return toStringCache;
798 StringBuffer buffer = new StringBuffer();
799 StringEscapeIterator it = new StringEscapeIterator(source);
800 while (it.hasNext()) {
801 buffer.addCharCode(it.next());
802 }
803 toStringCache = buffer.toString();
804 return toStringCache;
805 }
806 }
807
808 class ConsDartString extends DartString {
809 final DartString left;
810 final DartString right;
811 final int length;
812 int hashCache = null;
813 String toStringCache;
814 ConsDartString(DartString left, DartString right)
815 : this.left = left,
816 this.right = right,
817 length = left.length + right.length;
818
819 Iterator<int> iterator() => new ConsDartStringIterator(this);
820
821 String slowToString() {
822 if (toStringCache !== null) return toStringCache;
823 toStringCache = left.slowToString().concat(right.slowToString());
824 return toStringCache;
825 }
826 SourceString get source() => new StringWrapper(slowToString());
827 }
828
829 class ConsDartStringIterator implements Iterator<int> {
830 Iterator<int> current;
831 DartString right;
832 bool hasNextLookAhead;
833 ConsDartStringIterator(ConsDartString cons)
834 : current = cons.left.iterator(),
835 right = cons.right {
836 hasNextLookAhead = current.hasNext();
837 if (!hasNextLookAhead) {
838 nextPart();
839 }
840 }
841 bool hasNext() {
842 return hasNextLookAhead;
843 }
844 int next() {
845 assert(hasNextLookAhead);
846 int result = current.next();
847 hasNextLookAhead = current.hasNext();
848 if (!hasNextLookAhead) {
849 nextPart();
850 }
851 return result;
852 }
853 void nextPart() {
854 if (right !== null) {
855 current = right.iterator();
856 right = null;
857 hasNextLookAhead = current.hasNext();
858 }
859 }
860 }
861
862 /** 735 /**
863 *Iterator that returns the actual string contents of a string with escapes. 736 * Superclass for classes representing string literals.
864 */ 737 */
865 class StringEscapeIterator implements Iterator<int>{ 738 class StringNode extends Expression {
866 final Iterator<int> source; 739 abstract DartString get dartString();
867 StringEscapeIterator(SourceString source) : this.source = source.iterator(); 740 abstract bool get isInterpolation();
868 bool hasNext() => source.hasNext();
869 int next() {
870 int code = source.next();
871 if (code !== $BACKSLASH) {
872 return code;
873 }
874 code = source.next();
875 if (code === $n) return $LF;
876 if (code === $r) return $CR;
877 if (code === $t) return $TAB;
878 if (code === $b) return $BS;
879 if (code === $f) return $FF;
880 if (code === $v) return $VTAB;
881 if (code === $x) {
882 int value = hexDigitValue(source.next());
883 value = value * 16 + hexDigitValue(source.next());
884 return value;
885 }
886 if (code === $u) {
887 int value = 0;
888 code = source.next();
889 if (code === $OPEN_CURLY_BRACKET) {
890 for (code = source.next();
891 code != $CLOSE_CURLY_BRACKET;
892 code = source.next()) {
893 value = value * 16 + hexDigitValue(code);
894 }
895 return value;
896 }
897 // Four digit hex value.
898 value = hexDigitValue(code);
899 for (int i = 0; i < 3; i++) {
900 code = source.next();
901 value = value * 16 + hexDigitValue(code);
902 }
903 return value;
904 }
905 return code;
906 }
907 } 741 }
908 742
743 class LiteralString extends StringNode {
744 final Token token;
745 /** Non-null on validated string literals. */
746 final DartString dartString;
909 747
910 class LiteralString extends Literal<SourceString> { 748 LiteralString(this.token, this.dartString);
911 /** Set on validated string literals. */
912 final DartString dartString = null;
913
914 LiteralString(Token token, this.dartString) : super(token, null);
915 749
916 LiteralString asLiteralString() => this; 750 LiteralString asLiteralString() => this;
917 751
752 void visitChildren(Visitor visitor) {}
753
754 bool get isInterpolation() => false;
918 bool isValidated() => dartString !== null; 755 bool isValidated() => dartString !== null;
919 756
920 SourceString get value() => token.value; 757 Token getBeginToken() => token;
758 Token getEndToken() => token;
921 759
922 accept(Visitor visitor) => visitor.visitLiteralString(this); 760 accept(Visitor visitor) => visitor.visitLiteralString(this);
923 } 761 }
924 762
925 class LiteralNull extends Literal<SourceString> { 763 class LiteralNull extends Literal<SourceString> {
926 LiteralNull(Token token) : super(token, null); 764 LiteralNull(Token token) : super(token, null);
927 765
928 LiteralNull asLiteralNull() => this; 766 LiteralNull asLiteralNull() => this;
929 767
930 SourceString get value() => null; 768 SourceString get value() => null;
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 visitChildren(Visitor visitor) => nodes.accept(visitor); 1079 visitChildren(Visitor visitor) => nodes.accept(visitor);
1242 1080
1243 bool isStatic() => (flags & FLAG_STATIC) != 0; 1081 bool isStatic() => (flags & FLAG_STATIC) != 0;
1244 bool isAbstract() => (flags & FLAG_ABSTRACT) != 0; 1082 bool isAbstract() => (flags & FLAG_ABSTRACT) != 0;
1245 bool isFinal() => (flags & FLAG_FINAL) != 0; 1083 bool isFinal() => (flags & FLAG_FINAL) != 0;
1246 bool isVar() => (flags & FLAG_VAR) != 0; 1084 bool isVar() => (flags & FLAG_VAR) != 0;
1247 bool isConst() => (flags & FLAG_CONST) != 0; 1085 bool isConst() => (flags & FLAG_CONST) != 0;
1248 bool isFactory() => (flags & FLAG_FACTORY) != 0; 1086 bool isFactory() => (flags & FLAG_FACTORY) != 0;
1249 } 1087 }
1250 1088
1251 class StringInterpolation extends Expression { 1089 class StringInterpolation extends StringNode {
1252 final LiteralString string; 1090 final LiteralString string;
1253 final NodeList parts; 1091 final NodeList parts;
1254 1092
1255 StringInterpolation(this.string, this.parts); 1093 StringInterpolation(this.string, this.parts);
1256 1094
1257 StringInterpolation asStringInterpolation() => this; 1095 StringInterpolation asStringInterpolation() => this;
1258 1096
1097 DartString get dartString() => null;
1098 bool get isInterpolation() => true;
1099
1259 accept(Visitor visitor) => visitor.visitStringInterpolation(this); 1100 accept(Visitor visitor) => visitor.visitStringInterpolation(this);
1260 1101
1261 visitChildren(Visitor visitor) { 1102 visitChildren(Visitor visitor) {
1262 string.accept(visitor); 1103 string.accept(visitor);
1263 parts.accept(visitor); 1104 parts.accept(visitor);
1264 } 1105 }
1265 1106
1266 Token getBeginToken() => string.getBeginToken(); 1107 Token getBeginToken() => string.getBeginToken();
1267
1268 Token getEndToken() => parts.getEndToken(); 1108 Token getEndToken() => parts.getEndToken();
1269 } 1109 }
1270 1110
1271 class StringInterpolationPart extends Node { 1111 class StringInterpolationPart extends Node {
1272 final Expression expression; 1112 final Expression expression;
1273 final LiteralString string; 1113 final LiteralString string;
1274 1114
1275 StringInterpolationPart(this.expression, this.string); 1115 StringInterpolationPart(this.expression, this.string);
1276 1116
1277 StringInterpolationPart asStringInterpolationPart() => this; 1117 StringInterpolationPart asStringInterpolationPart() => this;
1278 1118
1279 accept(Visitor visitor) => visitor.visitStringInterpolationPart(this); 1119 accept(Visitor visitor) => visitor.visitStringInterpolationPart(this);
1280 1120
1281 visitChildren(Visitor visitor) { 1121 visitChildren(Visitor visitor) {
1282 expression.accept(visitor); 1122 expression.accept(visitor);
1283 string.accept(visitor); 1123 string.accept(visitor);
1284 } 1124 }
1285 1125
1286 Token getBeginToken() => expression.getBeginToken(); 1126 Token getBeginToken() => expression.getBeginToken();
1287 1127
1288 Token getEndToken() => string.getEndToken(); 1128 Token getEndToken() => string.getEndToken();
1289 } 1129 }
1290 1130
1291 class LiteralStringJuxtaposition extends LiteralString { 1131 /**
1292 // List of either StringLiteral or StringInterpolation. 1132 * A class representing juxtaposed string literals.
1293 final Link<Expression> literals; 1133 * The string literals can be both plain literals and string interpolations.
1134 */
1135 class StringJuxtaposition extends StringNode {
1136 final Expression first;
1137 final Expression second;
1138 // Caches the check for whether this juxtaposition contains a string
ahe 2012/03/19 14:44:20 Documentation comment.
Lasse Reichstein Nielsen 2012/03/19 15:07:33 Done.
1139 // interpolation
1140 bool _isInterpolation = null;
ahe 2012/03/19 14:44:20 I don't like package privacy.
Lasse Reichstein Nielsen 2012/03/19 15:07:33 But it's soooo conventient for making a variable i
1141 // Caches a Dart string representation of the entire juxtaposition's
ahe 2012/03/19 14:44:20 Documentation comment.
Lasse Reichstein Nielsen 2012/03/19 15:07:33 Done.
1142 // content. Only juxtapositions that don't (transitively) contains
1143 // interpolations have a static representation.
1144 DartString _dartString = null;
ahe 2012/03/19 14:44:20 privacy.
Lasse Reichstein Nielsen 2012/03/19 15:07:33 Done.
1294 1145
1295 LiteralStringJuxtaposition(Link<Expression> literals) 1146 StringJuxtaposition(this.first, this.second);
1296 : this.literals = literals,
1297 super(literals.head.getBeginToken(), concatenateLiterals(literals));
1298 1147
1299 static DartString concatenateLiterals(Link<Expression> literals) { 1148 StringJuxtaposition asStringJuxtaposition() => this;
1300 assert(!literals.isEmpty()); 1149
1301 LiteralString literal = literals.head; 1150 bool get isInterpolation() {
1302 if (literals.tail.isEmpty()) { 1151 if (_isInterpolation === null) {
1303 return literal.dartString; 1152 _isInterpolation = (first.accept(const IsInterpolationVisitor()) ||
1153 second.accept(const IsInterpolationVisitor()));
1304 } 1154 }
1305 return new ConsDartString(literal.dartString, 1155 return _isInterpolation;
1306 concatenateLiterals(literals.tail));
1307 } 1156 }
1308 1157
1309 SourceString get value() => null; 1158 /**
1310 1159 * Retrieve a single DartString that represents this entire juxtaposition
1311 accept(Visitor visitor) => visitor.visitLiteralStringJuxtaposition(this); 1160 * of string literals.
1312 1161 * Should only be called if [isInterpolation] returns false.
ahe 2012/03/19 14:44:20 Perhaps you should "assert" that. If the assertion
Lasse Reichstein Nielsen 2012/03/19 15:07:33 Done.
1313 visitChildren(Visitor visitor) { 1162 */
1314 for (Expression literal in literals) { 1163 DartString get dartString() {
1315 literal.accept(visitor); 1164 if (_dartString === null) {
1165 DartString firstString = first.accept(const GetDartStringVisitor());
1166 DartString secondString = second.accept(const GetDartStringVisitor());
1167 if (firstString === null || secondString === null) {
1168 return null;
1169 }
1170 _dartString = new DartString.concat(firstString, secondString);
1316 } 1171 }
1172 return _dartString;
1317 } 1173 }
1318 1174
1319 Token getBeginToken() => literals.head.getBeginToken(); 1175 accept(Visitor visitor) => visitor.visitStringJuxtaposition(this);
1320 1176
1321 Token getEndToken() { 1177 void visitChildren(Visitor visitor) {
1322 Link<Expression> current = literals; 1178 first.accept(visitor);
1323 Expression lastExpression = null; 1179 second.accept(visitor);
1324 while (!current.isEmpty()) {
1325 lastExpression = current.head;
1326 current = current.tail;
1327 }
1328 return lastExpression.getEndToken();
1329 } 1180 }
1181
1182 Token getBeginToken() => first.getBeginToken();
1183
1184 Token getEndToken() => second.getEndToken();
1330 } 1185 }
1331 1186
1332 class EmptyStatement extends Statement { 1187 class EmptyStatement extends Statement {
1333 final Token semicolonToken; 1188 final Token semicolonToken;
1334 1189
1335 EmptyStatement(this.semicolonToken); 1190 EmptyStatement(this.semicolonToken);
1336 1191
1337 EmptyStatement asEmptyStatement() => this; 1192 EmptyStatement asEmptyStatement() => this;
1338 1193
1339 accept(Visitor visitor) => visitor.visitEmptyStatement(this); 1194 accept(Visitor visitor) => visitor.visitEmptyStatement(this);
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 1444
1590 Node getBody() { 1445 Node getBody() {
1591 if (statement is! LabeledStatement) return statement; 1446 if (statement is! LabeledStatement) return statement;
1592 LabeledStatement labeled = statement; 1447 LabeledStatement labeled = statement;
1593 return labeled.getBody(); 1448 return labeled.getBody();
1594 } 1449 }
1595 } 1450 }
1596 1451
1597 class ScriptTag extends Node { 1452 class ScriptTag extends Node {
1598 final Identifier tag; 1453 final Identifier tag;
1599 final LiteralString argument; 1454 final StringNode argument;
1600 final Identifier prefixIdentifier; 1455 final Identifier prefixIdentifier;
1601 final LiteralString prefix; 1456 final StringNode prefix;
1602 1457
1603 final Token beginToken; 1458 final Token beginToken;
1604 final Token endToken; 1459 final Token endToken;
1605 1460
1606 ScriptTag(this.tag, this.argument, this.prefixIdentifier, this.prefix, 1461 ScriptTag(this.tag, this.argument, this.prefixIdentifier, this.prefix,
1607 this.beginToken, this.endToken); 1462 this.beginToken, this.endToken);
1608 1463
1609 bool isImport() => tag.source == const SourceString("import"); 1464 bool isImport() => tag.source == const SourceString("import");
1610 bool isSource() => tag.source == const SourceString("source"); 1465 bool isSource() => tag.source == const SourceString("source");
1611 bool isLibrary() => tag.source == const SourceString("library"); 1466 bool isLibrary() => tag.source == const SourceString("library");
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1734 static bool isConstructorRedirect(Send node) { 1589 static bool isConstructorRedirect(Send node) {
1735 return (node.receiver === null && 1590 return (node.receiver === null &&
1736 node.selector.asIdentifier() !== null && 1591 node.selector.asIdentifier() !== null &&
1737 node.selector.asIdentifier().isThis()) || 1592 node.selector.asIdentifier().isThis()) ||
1738 (node.receiver !== null && 1593 (node.receiver !== null &&
1739 node.receiver.asIdentifier() !== null && 1594 node.receiver.asIdentifier() !== null &&
1740 node.receiver.asIdentifier().isThis() && 1595 node.receiver.asIdentifier().isThis() &&
1741 node.selector.asIdentifier() !== null); 1596 node.selector.asIdentifier() !== null);
1742 } 1597 }
1743 } 1598 }
1599
1600 class GetDartStringVisitor extends AbstractVisitor<DartString> {
1601 const GetDartStringVisitor();
1602 DartString visitNode(Node node) => null;
1603 DartString visitStringJuxtaposition(StringJuxtaposition node)
1604 => node.dartString;
1605 DartString visitLiteralString(LiteralString node) => node.dartString;
1606 }
1607
1608 class IsInterpolationVisitor extends AbstractVisitor<bool> {
1609 const IsInterpolationVisitor();
1610 bool visitNode(Node node) => false;
1611 bool visitStringInterpolation(StringInterpolation node) => true;
1612 bool visitStringJuxtaposition(StringJuxtaposition node)
1613 => node.isInterpolation;
1614 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698