| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library trydart.interaction_manager; | 5 library trydart.interaction_manager; |
| 6 | 6 |
| 7 import 'dart:html'; | 7 import 'dart:html'; |
| 8 | 8 |
| 9 import 'dart:convert' show | 9 import 'dart:convert' show |
| 10 JSON; | 10 JSON; |
| 11 | 11 |
| 12 import 'dart:math' show | 12 import 'dart:math' show |
| 13 max, | 13 max, |
| 14 min; | 14 min; |
| 15 | 15 |
| 16 import 'dart:async' show | 16 import 'dart:async' show |
| 17 Completer, | 17 Completer, |
| 18 Future, | 18 Future, |
| 19 Timer; | 19 Timer; |
| 20 | 20 |
| 21 import 'dart:collection' show | 21 import 'dart:collection' show |
| 22 Queue; | 22 Queue; |
| 23 | 23 |
| 24 import 'package:compiler/implementation/scanner/scannerlib.dart' show | 24 import 'package:compiler/implementation/scanner/scannerlib.dart' show |
| 25 BeginGroupToken, | 25 BeginGroupToken, |
| 26 EOF_TOKEN, | 26 EOF_TOKEN, |
| 27 ErrorToken, | 27 ErrorToken, |
| 28 STRING_INTERPOLATION_IDENTIFIER_TOKEN, |
| 29 STRING_INTERPOLATION_TOKEN, |
| 30 STRING_TOKEN, |
| 28 StringScanner, | 31 StringScanner, |
| 29 Token, | 32 Token, |
| 30 UnmatchedToken, | 33 UnmatchedToken, |
| 31 UnterminatedToken; | 34 UnterminatedToken; |
| 32 | 35 |
| 33 import 'package:compiler/implementation/source_file.dart' show | 36 import 'package:compiler/implementation/source_file.dart' show |
| 34 StringSourceFile; | 37 StringSourceFile; |
| 35 | 38 |
| 39 import 'package:compiler/implementation/string_validator.dart' show |
| 40 StringValidator; |
| 41 |
| 42 import 'package:compiler/implementation/tree/tree.dart' show |
| 43 StringQuoting; |
| 44 |
| 36 import 'compilation.dart' show | 45 import 'compilation.dart' show |
| 37 currentSource, | 46 currentSource, |
| 38 startCompilation; | 47 startCompilation; |
| 39 | 48 |
| 40 import 'ui.dart' show | 49 import 'ui.dart' show |
| 41 currentTheme, | 50 currentTheme, |
| 42 hackDiv, | 51 hackDiv, |
| 43 mainEditorPane, | 52 mainEditorPane, |
| 44 observer, | 53 observer, |
| 45 outputDiv, | 54 outputDiv, |
| (...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1128 | 1137 |
| 1129 Token tokenToDecorate = token; | 1138 Token tokenToDecorate = token; |
| 1130 if (token is UnterminatedToken && isUnterminatedMultiLineToken(token)) { | 1139 if (token is UnterminatedToken && isUnterminatedMultiLineToken(token)) { |
| 1131 newState += '${token.start}'; | 1140 newState += '${token.start}'; |
| 1132 continue; // This might not be an error. | 1141 continue; // This might not be an error. |
| 1133 } else { | 1142 } else { |
| 1134 Token follow = token.next; | 1143 Token follow = token.next; |
| 1135 if (token is BeginGroupToken && token.endGroup != null) { | 1144 if (token is BeginGroupToken && token.endGroup != null) { |
| 1136 follow = token.endGroup.next; | 1145 follow = token.endGroup.next; |
| 1137 } | 1146 } |
| 1147 if (token.kind == STRING_TOKEN) { |
| 1148 follow = followString(follow); |
| 1149 if (follow is UnmatchedToken) { |
| 1150 if ('${follow.begin.value}' == r'${') { |
| 1151 newState += '${extractQuote(token.value)}'; |
| 1152 } |
| 1153 } |
| 1154 } |
| 1138 if (follow is ErrorToken && follow.charOffset == token.charOffset) { | 1155 if (follow is ErrorToken && follow.charOffset == token.charOffset) { |
| 1139 if (follow is UnmatchedToken) { | 1156 if (follow is UnmatchedToken) { |
| 1140 newState += '${follow.begin.value}'; | 1157 newState += '${follow.begin.value}'; |
| 1141 } else { | 1158 } else { |
| 1142 tokenToDecorate = follow; | 1159 tokenToDecorate = follow; |
| 1143 } | 1160 } |
| 1144 } | 1161 } |
| 1145 } | 1162 } |
| 1146 | 1163 |
| 1147 if (charOffset < offset) { | 1164 if (charOffset < offset) { |
| 1148 // Happens for scanner errors, or for the [state] prefix. | 1165 // Happens for scanner errors, or for the [state] prefix. |
| 1149 continue; | 1166 continue; |
| 1150 } | 1167 } |
| 1151 | 1168 |
| 1152 Decoration decoration = editor.getDecoration(tokenToDecorate); | 1169 Decoration decoration; |
| 1170 if (charOffset - state.length == line.length - 1 && line.endsWith('\n')) { |
| 1171 // Don't add decorations to trailing newline. |
| 1172 decoration = null; |
| 1173 } else { |
| 1174 decoration = editor.getDecoration(tokenToDecorate); |
| 1175 } |
| 1153 | 1176 |
| 1154 if (decoration == null) continue; | 1177 if (decoration == null) continue; |
| 1155 | 1178 |
| 1156 // Add a node for text before current token. | 1179 // Add a node for text before current token. |
| 1157 trySelection.addNodeFromSubstring( | 1180 trySelection.addNodeFromSubstring( |
| 1158 adjustedStart + offset, adjustedStart + charOffset, nodes); | 1181 adjustedStart + offset, adjustedStart + charOffset, nodes); |
| 1159 | 1182 |
| 1160 // Add a node for current token. | 1183 // Add a node for current token. |
| 1161 trySelection.addNodeFromSubstring( | 1184 trySelection.addNodeFromSubstring( |
| 1162 adjustedStart + charOffset, | 1185 adjustedStart + charOffset, |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 // Safari can also reach this code, but the offset isn't wrong, just | 1298 // Safari can also reach this code, but the offset isn't wrong, just |
| 1276 // inconsistent. After moving the cursor back and forth, Safari will make | 1299 // inconsistent. After moving the cursor back and forth, Safari will make |
| 1277 // the offset relative to a text node. | 1300 // the offset relative to a text node. |
| 1278 selection | 1301 selection |
| 1279 ..modify('move', 'backward', 'character') | 1302 ..modify('move', 'backward', 'character') |
| 1280 ..modify('move', 'forward', 'character'); | 1303 ..modify('move', 'forward', 'character'); |
| 1281 print('Selection adjusted $node@$offset -> ' | 1304 print('Selection adjusted $node@$offset -> ' |
| 1282 '${selection.anchorNode}@${selection.anchorOffset}.'); | 1305 '${selection.anchorNode}@${selection.anchorOffset}.'); |
| 1283 } | 1306 } |
| 1284 } | 1307 } |
| 1308 |
| 1309 /// Compute the token following a string. Compare to parseSingleLiteralString |
| 1310 /// in parser.dart. |
| 1311 Token followString(Token token) { |
| 1312 // TODO(ahe): I should be able to get rid of this if I change the scanner to |
| 1313 // create BeginGroupToken for strings. |
| 1314 int kind = token.kind; |
| 1315 while (kind != EOF_TOKEN) { |
| 1316 if (kind == STRING_INTERPOLATION_TOKEN) { |
| 1317 // Looking at ${expression}. |
| 1318 BeginGroupToken begin = token; |
| 1319 token = begin.endGroup.next; |
| 1320 } else if (kind == STRING_INTERPOLATION_IDENTIFIER_TOKEN) { |
| 1321 // Looking at $identifier. |
| 1322 token = token.next.next; |
| 1323 } else { |
| 1324 return token; |
| 1325 } |
| 1326 kind = token.kind; |
| 1327 if (kind != STRING_TOKEN) return token; |
| 1328 token = token.next; |
| 1329 kind = token.kind; |
| 1330 } |
| 1331 return token; |
| 1332 } |
| 1333 |
| 1334 String extractQuote(String string) { |
| 1335 StringQuoting q = StringValidator.quotingFromString(string); |
| 1336 return (q.raw ? 'r' : '') + (q.quoteChar * q.leftQuoteLength); |
| 1337 } |
| OLD | NEW |