| OLD | NEW |
| 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); |
| 41 R visitStringInterpolation(StringInterpolation node); | 41 R visitStringInterpolation(StringInterpolation node); |
| 42 R visitStringInterpolationPart(StringInterpolationPart node); | 42 R visitStringInterpolationPart(StringInterpolationPart node); |
| 43 R visitSwitchCase(SwitchCase node); | 43 R visitSwitchCase(SwitchCase node); |
| 44 R visitSwitchStatement(SwitchStatement node); | 44 R visitSwitchStatement(SwitchStatement node); |
| 45 R visitThrow(Throw node); | 45 R visitThrow(Throw node); |
| 46 R visitTryStatement(TryStatement node); | 46 R visitTryStatement(TryStatement node); |
| 47 R visitTypeAnnotation(TypeAnnotation node); | 47 R visitTypeAnnotation(TypeAnnotation node); |
| 48 R visitTypedef(Typedef node); | 48 R visitTypedef(Typedef node); |
| 49 R visitTypeVariable(TypeVariable node); | 49 R visitTypeVariable(TypeVariable node); |
| 50 R visitVariableDefinitions(VariableDefinitions node); | 50 R visitVariableDefinitions(VariableDefinitions node); |
| 51 R visitWhile(While node); | 51 R visitWhile(While node); |
| 52 } | 52 } |
| 53 | 53 |
| 54 Token firstBeginToken(Node first, Node second) { | 54 Token firstBeginToken(Node first, Node second) { |
| 55 if (first !== null) return first.getBeginToken(); | 55 if (first !== null) return first.getBeginToken(); |
| 56 if (second !== null) return second.getBeginToken(); | 56 if (second !== null) return second.getBeginToken(); |
| 57 return null; | 57 return null; |
| 58 } | 58 } |
| 59 | 59 |
| 60 class NodeAssertionFailure implements Exception { |
| 61 final Node node; |
| 62 final String message; |
| 63 NodeAssertionFailure(this.node, this.message); |
| 64 } |
| 65 |
| 60 /** | 66 /** |
| 61 * A node in a syntax tree. | 67 * A node in a syntax tree. |
| 62 * | 68 * |
| 63 * The abstract part of "abstract syntax tree" is invalidated when | 69 * The abstract part of "abstract syntax tree" is invalidated when |
| 64 * supporting tools such as code formatting. These tools need concrete | 70 * supporting tools such as code formatting. These tools need concrete |
| 65 * syntax such as parentheses and no constant folding. | 71 * syntax such as parentheses and no constant folding. |
| 66 * | 72 * |
| 67 * We support these tools by storing additional references back to the | 73 * We support these tools by storing additional references back to the |
| 68 * token stream. These references are stored in fields ending with | 74 * token stream. These references are stored in fields ending with |
| 69 * "Token". | 75 * "Token". |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 NodeList asNodeList() => null; | 136 NodeList asNodeList() => null; |
| 131 Operator asOperator() => null; | 137 Operator asOperator() => null; |
| 132 ParenthesizedExpression asParenthesizedExpression() => null; | 138 ParenthesizedExpression asParenthesizedExpression() => null; |
| 133 Return asReturn() => null; | 139 Return asReturn() => null; |
| 134 ScriptTag asScriptTag() => null; | 140 ScriptTag asScriptTag() => null; |
| 135 Send asSend() => null; | 141 Send asSend() => null; |
| 136 SendSet asSendSet() => null; | 142 SendSet asSendSet() => null; |
| 137 Statement asStatement() => null; | 143 Statement asStatement() => null; |
| 138 StringInterpolation asStringInterpolation() => null; | 144 StringInterpolation asStringInterpolation() => null; |
| 139 StringInterpolationPart asStringInterpolationPart() => null; | 145 StringInterpolationPart asStringInterpolationPart() => null; |
| 146 StringJuxtaposition asStringJuxtaposition() => null; |
| 140 SwitchCase asSwitchCase() => null; | 147 SwitchCase asSwitchCase() => null; |
| 141 SwitchStatement asSwitchStatement() => null; | 148 SwitchStatement asSwitchStatement() => null; |
| 142 Throw asThrow() => null; | 149 Throw asThrow() => null; |
| 143 TryStatement asTryStatement() => null; | 150 TryStatement asTryStatement() => null; |
| 144 TypeAnnotation asTypeAnnotation() => null; | 151 TypeAnnotation asTypeAnnotation() => null; |
| 145 Typedef asTypedef() => null; | 152 Typedef asTypedef() => null; |
| 146 TypeVariable asTypeVariable() => null; | 153 TypeVariable asTypeVariable() => null; |
| 147 VariableDefinitions asVariableDefinitions() => null; | 154 VariableDefinitions asVariableDefinitions() => null; |
| 148 While asWhile() => null; | 155 While asWhile() => null; |
| 149 | 156 |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 | 731 |
| 725 int get leftQuoteLength() => (raw ? 1 : 0) + leftQuoteCharCount; | 732 int get leftQuoteLength() => (raw ? 1 : 0) + leftQuoteCharCount; |
| 726 int get rightQuoteLength() => (leftQuoteCharCount > 2) ? 3 : 1; | 733 int get rightQuoteLength() => (leftQuoteCharCount > 2) ? 3 : 1; |
| 727 static StringQuoting getQuoting(int quote, bool raw, int quoteLength) { | 734 static StringQuoting getQuoting(int quote, bool raw, int quoteLength) { |
| 728 int index = quoteLength - 1; | 735 int index = quoteLength - 1; |
| 729 if (quoteLength > 2) index -= 1; | 736 if (quoteLength > 2) index -= 1; |
| 730 return mapping[(raw ? 1 : 0) + index * 2 + (quote === $SQ ? 8 : 0)]; | 737 return mapping[(raw ? 1 : 0) + index * 2 + (quote === $SQ ? 8 : 0)]; |
| 731 } | 738 } |
| 732 } | 739 } |
| 733 | 740 |
| 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 /** | 741 /** |
| 863 *Iterator that returns the actual string contents of a string with escapes. | 742 * Superclass for classes representing string literals. |
| 864 */ | 743 */ |
| 865 class StringEscapeIterator implements Iterator<int>{ | 744 class StringNode extends Expression { |
| 866 final Iterator<int> source; | 745 abstract DartString get dartString(); |
| 867 StringEscapeIterator(SourceString source) : this.source = source.iterator(); | 746 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 } | 747 } |
| 908 | 748 |
| 749 class LiteralString extends StringNode { |
| 750 final Token token; |
| 751 /** Non-null on validated string literals. */ |
| 752 final DartString dartString; |
| 909 | 753 |
| 910 class LiteralString extends Literal<SourceString> { | 754 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 | 755 |
| 916 LiteralString asLiteralString() => this; | 756 LiteralString asLiteralString() => this; |
| 917 | 757 |
| 758 void visitChildren(Visitor visitor) {} |
| 759 |
| 760 bool get isInterpolation() => false; |
| 918 bool isValidated() => dartString !== null; | 761 bool isValidated() => dartString !== null; |
| 919 | 762 |
| 920 SourceString get value() => token.value; | 763 Token getBeginToken() => token; |
| 764 Token getEndToken() => token; |
| 921 | 765 |
| 922 accept(Visitor visitor) => visitor.visitLiteralString(this); | 766 accept(Visitor visitor) => visitor.visitLiteralString(this); |
| 923 } | 767 } |
| 924 | 768 |
| 925 class LiteralNull extends Literal<SourceString> { | 769 class LiteralNull extends Literal<SourceString> { |
| 926 LiteralNull(Token token) : super(token, null); | 770 LiteralNull(Token token) : super(token, null); |
| 927 | 771 |
| 928 LiteralNull asLiteralNull() => this; | 772 LiteralNull asLiteralNull() => this; |
| 929 | 773 |
| 930 SourceString get value() => null; | 774 SourceString get value() => null; |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 visitChildren(Visitor visitor) => nodes.accept(visitor); | 1085 visitChildren(Visitor visitor) => nodes.accept(visitor); |
| 1242 | 1086 |
| 1243 bool isStatic() => (flags & FLAG_STATIC) != 0; | 1087 bool isStatic() => (flags & FLAG_STATIC) != 0; |
| 1244 bool isAbstract() => (flags & FLAG_ABSTRACT) != 0; | 1088 bool isAbstract() => (flags & FLAG_ABSTRACT) != 0; |
| 1245 bool isFinal() => (flags & FLAG_FINAL) != 0; | 1089 bool isFinal() => (flags & FLAG_FINAL) != 0; |
| 1246 bool isVar() => (flags & FLAG_VAR) != 0; | 1090 bool isVar() => (flags & FLAG_VAR) != 0; |
| 1247 bool isConst() => (flags & FLAG_CONST) != 0; | 1091 bool isConst() => (flags & FLAG_CONST) != 0; |
| 1248 bool isFactory() => (flags & FLAG_FACTORY) != 0; | 1092 bool isFactory() => (flags & FLAG_FACTORY) != 0; |
| 1249 } | 1093 } |
| 1250 | 1094 |
| 1251 class StringInterpolation extends Expression { | 1095 class StringInterpolation extends StringNode { |
| 1252 final LiteralString string; | 1096 final LiteralString string; |
| 1253 final NodeList parts; | 1097 final NodeList parts; |
| 1254 | 1098 |
| 1255 StringInterpolation(this.string, this.parts); | 1099 StringInterpolation(this.string, this.parts); |
| 1256 | 1100 |
| 1257 StringInterpolation asStringInterpolation() => this; | 1101 StringInterpolation asStringInterpolation() => this; |
| 1258 | 1102 |
| 1103 DartString get dartString() => null; |
| 1104 bool get isInterpolation() => true; |
| 1105 |
| 1259 accept(Visitor visitor) => visitor.visitStringInterpolation(this); | 1106 accept(Visitor visitor) => visitor.visitStringInterpolation(this); |
| 1260 | 1107 |
| 1261 visitChildren(Visitor visitor) { | 1108 visitChildren(Visitor visitor) { |
| 1262 string.accept(visitor); | 1109 string.accept(visitor); |
| 1263 parts.accept(visitor); | 1110 parts.accept(visitor); |
| 1264 } | 1111 } |
| 1265 | 1112 |
| 1266 Token getBeginToken() => string.getBeginToken(); | 1113 Token getBeginToken() => string.getBeginToken(); |
| 1267 | |
| 1268 Token getEndToken() => parts.getEndToken(); | 1114 Token getEndToken() => parts.getEndToken(); |
| 1269 } | 1115 } |
| 1270 | 1116 |
| 1271 class StringInterpolationPart extends Node { | 1117 class StringInterpolationPart extends Node { |
| 1272 final Expression expression; | 1118 final Expression expression; |
| 1273 final LiteralString string; | 1119 final LiteralString string; |
| 1274 | 1120 |
| 1275 StringInterpolationPart(this.expression, this.string); | 1121 StringInterpolationPart(this.expression, this.string); |
| 1276 | 1122 |
| 1277 StringInterpolationPart asStringInterpolationPart() => this; | 1123 StringInterpolationPart asStringInterpolationPart() => this; |
| 1278 | 1124 |
| 1279 accept(Visitor visitor) => visitor.visitStringInterpolationPart(this); | 1125 accept(Visitor visitor) => visitor.visitStringInterpolationPart(this); |
| 1280 | 1126 |
| 1281 visitChildren(Visitor visitor) { | 1127 visitChildren(Visitor visitor) { |
| 1282 expression.accept(visitor); | 1128 expression.accept(visitor); |
| 1283 string.accept(visitor); | 1129 string.accept(visitor); |
| 1284 } | 1130 } |
| 1285 | 1131 |
| 1286 Token getBeginToken() => expression.getBeginToken(); | 1132 Token getBeginToken() => expression.getBeginToken(); |
| 1287 | 1133 |
| 1288 Token getEndToken() => string.getEndToken(); | 1134 Token getEndToken() => string.getEndToken(); |
| 1289 } | 1135 } |
| 1290 | 1136 |
| 1291 class LiteralStringJuxtaposition extends LiteralString { | 1137 /** |
| 1292 // List of either StringLiteral or StringInterpolation. | 1138 * A class representing juxtaposed string literals. |
| 1293 final Link<Expression> literals; | 1139 * The string literals can be both plain literals and string interpolations. |
| 1140 */ |
| 1141 class StringJuxtaposition extends StringNode { |
| 1142 final Expression first; |
| 1143 final Expression second; |
| 1294 | 1144 |
| 1295 LiteralStringJuxtaposition(Link<Expression> literals) | 1145 /** |
| 1296 : this.literals = literals, | 1146 * Caches the check for whether this juxtaposition contains a string |
| 1297 super(literals.head.getBeginToken(), concatenateLiterals(literals)); | 1147 * interpolation |
| 1148 */ |
| 1149 bool isInterpolationCache = null; |
| 1298 | 1150 |
| 1299 static DartString concatenateLiterals(Link<Expression> literals) { | 1151 /** |
| 1300 assert(!literals.isEmpty()); | 1152 * Caches a Dart string representation of the entire juxtaposition's |
| 1301 LiteralString literal = literals.head; | 1153 * content. Only juxtapositions that don't (transitively) contains |
| 1302 if (literals.tail.isEmpty()) { | 1154 * interpolations have a static representation. |
| 1303 return literal.dartString; | 1155 */ |
| 1156 DartString dartStringCache = null; |
| 1157 |
| 1158 StringJuxtaposition(this.first, this.second); |
| 1159 |
| 1160 StringJuxtaposition asStringJuxtaposition() => this; |
| 1161 |
| 1162 bool get isInterpolation() { |
| 1163 if (isInterpolationCache === null) { |
| 1164 isInterpolationCache = (first.accept(const IsInterpolationVisitor()) || |
| 1165 second.accept(const IsInterpolationVisitor())); |
| 1304 } | 1166 } |
| 1305 return new ConsDartString(literal.dartString, | 1167 return isInterpolationCache; |
| 1306 concatenateLiterals(literals.tail)); | |
| 1307 } | 1168 } |
| 1308 | 1169 |
| 1309 SourceString get value() => null; | 1170 /** |
| 1310 | 1171 * Retrieve a single DartString that represents this entire juxtaposition |
| 1311 accept(Visitor visitor) => visitor.visitLiteralStringJuxtaposition(this); | 1172 * of string literals. |
| 1312 | 1173 * Should only be called if [isInterpolation] returns false. |
| 1313 visitChildren(Visitor visitor) { | 1174 */ |
| 1314 for (Expression literal in literals) { | 1175 DartString get dartString() { |
| 1315 literal.accept(visitor); | 1176 if (isInterpolation) { |
| 1177 throw new NodeAssertionFailure(this, |
| 1178 "Getting dartString on interpolation;"); |
| 1316 } | 1179 } |
| 1180 if (dartStringCache === null) { |
| 1181 DartString firstString = first.accept(const GetDartStringVisitor()); |
| 1182 DartString secondString = second.accept(const GetDartStringVisitor()); |
| 1183 if (firstString === null || secondString === null) { |
| 1184 return null; |
| 1185 } |
| 1186 dartStringCache = new DartString.concat(firstString, secondString); |
| 1187 } |
| 1188 return dartStringCache; |
| 1317 } | 1189 } |
| 1318 | 1190 |
| 1319 Token getBeginToken() => literals.head.getBeginToken(); | 1191 accept(Visitor visitor) => visitor.visitStringJuxtaposition(this); |
| 1320 | 1192 |
| 1321 Token getEndToken() { | 1193 void visitChildren(Visitor visitor) { |
| 1322 Link<Expression> current = literals; | 1194 first.accept(visitor); |
| 1323 Expression lastExpression = null; | 1195 second.accept(visitor); |
| 1324 while (!current.isEmpty()) { | |
| 1325 lastExpression = current.head; | |
| 1326 current = current.tail; | |
| 1327 } | |
| 1328 return lastExpression.getEndToken(); | |
| 1329 } | 1196 } |
| 1197 |
| 1198 Token getBeginToken() => first.getBeginToken(); |
| 1199 |
| 1200 Token getEndToken() => second.getEndToken(); |
| 1330 } | 1201 } |
| 1331 | 1202 |
| 1332 class EmptyStatement extends Statement { | 1203 class EmptyStatement extends Statement { |
| 1333 final Token semicolonToken; | 1204 final Token semicolonToken; |
| 1334 | 1205 |
| 1335 EmptyStatement(this.semicolonToken); | 1206 EmptyStatement(this.semicolonToken); |
| 1336 | 1207 |
| 1337 EmptyStatement asEmptyStatement() => this; | 1208 EmptyStatement asEmptyStatement() => this; |
| 1338 | 1209 |
| 1339 accept(Visitor visitor) => visitor.visitEmptyStatement(this); | 1210 accept(Visitor visitor) => visitor.visitEmptyStatement(this); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 | 1460 |
| 1590 Node getBody() { | 1461 Node getBody() { |
| 1591 if (statement is! LabeledStatement) return statement; | 1462 if (statement is! LabeledStatement) return statement; |
| 1592 LabeledStatement labeled = statement; | 1463 LabeledStatement labeled = statement; |
| 1593 return labeled.getBody(); | 1464 return labeled.getBody(); |
| 1594 } | 1465 } |
| 1595 } | 1466 } |
| 1596 | 1467 |
| 1597 class ScriptTag extends Node { | 1468 class ScriptTag extends Node { |
| 1598 final Identifier tag; | 1469 final Identifier tag; |
| 1599 final LiteralString argument; | 1470 final StringNode argument; |
| 1600 final Identifier prefixIdentifier; | 1471 final Identifier prefixIdentifier; |
| 1601 final LiteralString prefix; | 1472 final StringNode prefix; |
| 1602 | 1473 |
| 1603 final Token beginToken; | 1474 final Token beginToken; |
| 1604 final Token endToken; | 1475 final Token endToken; |
| 1605 | 1476 |
| 1606 ScriptTag(this.tag, this.argument, this.prefixIdentifier, this.prefix, | 1477 ScriptTag(this.tag, this.argument, this.prefixIdentifier, this.prefix, |
| 1607 this.beginToken, this.endToken); | 1478 this.beginToken, this.endToken); |
| 1608 | 1479 |
| 1609 bool isImport() => tag.source == const SourceString("import"); | 1480 bool isImport() => tag.source == const SourceString("import"); |
| 1610 bool isSource() => tag.source == const SourceString("source"); | 1481 bool isSource() => tag.source == const SourceString("source"); |
| 1611 bool isLibrary() => tag.source == const SourceString("library"); | 1482 bool isLibrary() => tag.source == const SourceString("library"); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1734 static bool isConstructorRedirect(Send node) { | 1605 static bool isConstructorRedirect(Send node) { |
| 1735 return (node.receiver === null && | 1606 return (node.receiver === null && |
| 1736 node.selector.asIdentifier() !== null && | 1607 node.selector.asIdentifier() !== null && |
| 1737 node.selector.asIdentifier().isThis()) || | 1608 node.selector.asIdentifier().isThis()) || |
| 1738 (node.receiver !== null && | 1609 (node.receiver !== null && |
| 1739 node.receiver.asIdentifier() !== null && | 1610 node.receiver.asIdentifier() !== null && |
| 1740 node.receiver.asIdentifier().isThis() && | 1611 node.receiver.asIdentifier().isThis() && |
| 1741 node.selector.asIdentifier() !== null); | 1612 node.selector.asIdentifier() !== null); |
| 1742 } | 1613 } |
| 1743 } | 1614 } |
| 1615 |
| 1616 class GetDartStringVisitor extends AbstractVisitor<DartString> { |
| 1617 const GetDartStringVisitor(); |
| 1618 DartString visitNode(Node node) => null; |
| 1619 DartString visitStringJuxtaposition(StringJuxtaposition node) |
| 1620 => node.dartString; |
| 1621 DartString visitLiteralString(LiteralString node) => node.dartString; |
| 1622 } |
| 1623 |
| 1624 class IsInterpolationVisitor extends AbstractVisitor<bool> { |
| 1625 const IsInterpolationVisitor(); |
| 1626 bool visitNode(Node node) => false; |
| 1627 bool visitStringInterpolation(StringInterpolation node) => true; |
| 1628 bool visitStringJuxtaposition(StringJuxtaposition node) |
| 1629 => node.isInterpolation; |
| 1630 } |
| OLD | NEW |