| Index: dart/site/try/src/interaction_manager.dart
|
| diff --git a/dart/site/try/src/interaction_manager.dart b/dart/site/try/src/interaction_manager.dart
|
| index 1422e1968d1ef805f92e589a619f2aa97ec71563..2a92fe16d78625cdef33361f1c4bbd935a0e3e6d 100644
|
| --- a/dart/site/try/src/interaction_manager.dart
|
| +++ b/dart/site/try/src/interaction_manager.dart
|
| @@ -21,7 +21,9 @@ import 'package:compiler/implementation/scanner/scannerlib.dart' show
|
| EOF_TOKEN,
|
| ErrorToken,
|
| StringScanner,
|
| - Token;
|
| + Token,
|
| + UnmatchedToken,
|
| + UnterminatedToken;
|
|
|
| import 'package:compiler/implementation/source_file.dart' show
|
| StringSourceFile;
|
| @@ -274,7 +276,16 @@ class InitialState extends InteractionState {
|
| int offset = 0;
|
| List<Node> nodes = <Node>[];
|
|
|
| - tokenizeAndHighlight(currentText, offset, trySelection, nodes);
|
| + String state = '';
|
| + for (String line in currentText.split(new RegExp('^', multiLine: true))) {
|
| + List<Node> lineNodes = <Node>[];
|
| + state =
|
| + tokenizeAndHighlight(line, state, offset, trySelection, lineNodes);
|
| + offset += line.length;
|
| + nodes.add(new SpanElement()
|
| + ..nodes.addAll(lineNodes)
|
| + ..classes.add('lineNumber'));
|
| + }
|
|
|
| mainEditorPane
|
| ..nodes.clear()
|
| @@ -700,50 +711,77 @@ bool computeHasModifier(KeyboardEvent event) {
|
| event.getModifierState("OS");
|
| }
|
|
|
| -void tokenizeAndHighlight(String currentText,
|
| - int offset,
|
| - TrySelection trySelection,
|
| - List<Node> nodes) {
|
| +String tokenizeAndHighlight(String line,
|
| + String state,
|
| + int start,
|
| + TrySelection trySelection,
|
| + List<Node> nodes) {
|
| + String newState = '';
|
| + int offset = state.length;
|
| + int adjustedStart = start - state.length;
|
| +
|
| // + offset + charOffset + globalOffset + (charOffset + charCount)
|
| // v v v v
|
| // do identifier_abcdefghijklmnopqrst
|
| - for (Token token = tokenize(currentText);
|
| + for (Token token = tokenize('$state$line');
|
| token.kind != EOF_TOKEN;
|
| token = token.next) {
|
| int charOffset = token.charOffset;
|
| int charCount = token.charCount;
|
|
|
| - if (charOffset < offset) continue; // Happens for scanner errors.
|
| -
|
| - Decoration decoration = editor.getDecoration(token);
|
| -
|
| - Token follow = token.next;
|
| - if (token is BeginGroupToken) {
|
| - follow = token.endGroup.next;
|
| + Token tokenToDecorate = token;
|
| + if (token is UnterminatedToken && isUnterminatedMultiLineToken(token)) {
|
| + newState += '${token.start}';
|
| + continue; // This might not be an error.
|
| + } else {
|
| + Token follow = token.next;
|
| + if (token is BeginGroupToken && token.endGroup != null) {
|
| + follow = token.endGroup.next;
|
| + }
|
| + if (follow is ErrorToken && follow.charOffset == token.charOffset) {
|
| + if (follow is UnmatchedToken) {
|
| + newState += '${follow.begin.value}';
|
| + } else {
|
| + tokenToDecorate = follow;
|
| + }
|
| + }
|
| }
|
| - if (follow is ErrorToken) {
|
| - decoration = editor.getDecoration(follow);
|
| +
|
| + if (charOffset < offset) {
|
| + // Happens for scanner errors, or for the [state] prefix.
|
| + continue;
|
| }
|
|
|
| + Decoration decoration = editor.getDecoration(tokenToDecorate);
|
| +
|
| if (decoration == null) continue;
|
|
|
| // Add a node for text before current token.
|
| - trySelection.addNodeFromSubstring(offset, charOffset, nodes);
|
| + trySelection.addNodeFromSubstring(
|
| + adjustedStart + offset, adjustedStart + charOffset, nodes);
|
|
|
| // Add a node for current token.
|
| trySelection.addNodeFromSubstring(
|
| - charOffset, charOffset + charCount, nodes, decoration);
|
| + adjustedStart + charOffset,
|
| + adjustedStart + charOffset + charCount, nodes, decoration);
|
|
|
| offset = charOffset + charCount;
|
| }
|
|
|
| // Add a node for anything after the last (decorated) token.
|
| - trySelection.addNodeFromSubstring(offset, currentText.length, nodes);
|
| + trySelection.addNodeFromSubstring(
|
| + adjustedStart + offset, start + line.length, nodes);
|
|
|
| - // Ensure text always ends with a newline.
|
| - if (!currentText.endsWith('\n')) {
|
| - nodes.add(new Text('\n'));
|
| - }
|
| + return newState;
|
| +}
|
| +
|
| +bool isUnterminatedMultiLineToken(UnterminatedToken token) {
|
| + return
|
| + token.start == '/*' ||
|
| + token.start == "'''" ||
|
| + token.start == '"""' ||
|
| + token.start == "r'''" ||
|
| + token.start == 'r"""';
|
| }
|
|
|
| void normalizeMutationRecord(MutationRecord record, TrySelection selection) {
|
|
|