Chromium Code Reviews| 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 Future; | 17 Future; |
| 18 | 18 |
| 19 import 'package:compiler/implementation/scanner/scannerlib.dart' show | 19 import 'package:compiler/implementation/scanner/scannerlib.dart' show |
| 20 BeginGroupToken, | 20 BeginGroupToken, |
| 21 EOF_TOKEN, | 21 EOF_TOKEN, |
| 22 ErrorToken, | 22 ErrorToken, |
| 23 StringScanner, | 23 StringScanner, |
| 24 Token; | 24 Token, |
| 25 UnmatchedToken, | |
| 26 UnterminatedToken; | |
| 25 | 27 |
| 26 import 'package:compiler/implementation/source_file.dart' show | 28 import 'package:compiler/implementation/source_file.dart' show |
| 27 StringSourceFile; | 29 StringSourceFile; |
| 28 | 30 |
| 29 import 'compilation.dart' show | 31 import 'compilation.dart' show |
| 30 currentSource, | 32 currentSource, |
| 31 scheduleCompilation; | 33 scheduleCompilation; |
| 32 | 34 |
| 33 import 'ui.dart' show | 35 import 'ui.dart' show |
| 34 currentTheme, | 36 currentTheme, |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 trySelection.updateText(currentText); | 269 trySelection.updateText(currentText); |
| 268 | 270 |
| 269 context.currentCompilationUnit.content = currentText; | 271 context.currentCompilationUnit.content = currentText; |
| 270 | 272 |
| 271 editor.seenIdentifiers = new Set<String>.from(mock.identifiers); | 273 editor.seenIdentifiers = new Set<String>.from(mock.identifiers); |
| 272 | 274 |
| 273 editor.isMalformedInput = false; | 275 editor.isMalformedInput = false; |
| 274 int offset = 0; | 276 int offset = 0; |
| 275 List<Node> nodes = <Node>[]; | 277 List<Node> nodes = <Node>[]; |
| 276 | 278 |
| 277 tokenizeAndHighlight(currentText, offset, trySelection, nodes); | 279 String state = ''; |
| 280 for (String line in currentText.split(new RegExp('^', multiLine: true))) { | |
| 281 List<Node> lineNodes = <Node>[]; | |
| 282 state = | |
| 283 tokenizeAndHighlight(line, state, offset, trySelection, lineNodes); | |
| 284 offset += line.length; | |
| 285 nodes.add(new SpanElement() | |
| 286 ..nodes.addAll(lineNodes) | |
| 287 ..classes.add('lineNumber')); | |
| 288 } | |
| 278 | 289 |
| 279 mainEditorPane | 290 mainEditorPane |
| 280 ..nodes.clear() | 291 ..nodes.clear() |
| 281 ..nodes.addAll(nodes); | 292 ..nodes.addAll(nodes); |
| 282 trySelection.adjust(selection); | 293 trySelection.adjust(selection); |
| 283 | 294 |
| 284 // Discard highlighting mutations. | 295 // Discard highlighting mutations. |
| 285 observer.takeRecords(); | 296 observer.takeRecords(); |
| 286 } | 297 } |
| 287 | 298 |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 event.getModifierState("Meta") || | 704 event.getModifierState("Meta") || |
| 694 event.getModifierState("NumLock") || | 705 event.getModifierState("NumLock") || |
| 695 event.getModifierState("ScrollLock") || | 706 event.getModifierState("ScrollLock") || |
| 696 event.getModifierState("Scroll") || | 707 event.getModifierState("Scroll") || |
| 697 event.getModifierState("Win") || | 708 event.getModifierState("Win") || |
| 698 event.getModifierState("Shift") || | 709 event.getModifierState("Shift") || |
| 699 event.getModifierState("SymbolLock") || | 710 event.getModifierState("SymbolLock") || |
| 700 event.getModifierState("OS"); | 711 event.getModifierState("OS"); |
| 701 } | 712 } |
| 702 | 713 |
| 703 void tokenizeAndHighlight(String currentText, | 714 String tokenizeAndHighlight(String line, |
| 704 int offset, | 715 String state, |
| 705 TrySelection trySelection, | 716 int start, |
| 706 List<Node> nodes) { | 717 TrySelection trySelection, |
| 718 List<Node> nodes) { | |
| 719 String newState = ''; | |
|
kasperl
2014/05/02 08:01:06
Consider using a StringBuffer or += to build the n
ahe
2014/05/02 10:01:45
I knew the other version would generate nice JS co
| |
| 720 int offset = state.length; | |
| 707 // + offset + charOffset + globalOffset + (charOffset + charCount) | 721 // + offset + charOffset + globalOffset + (charOffset + charCount) |
| 708 // v v v v | 722 // v v v v |
| 709 // do identifier_abcdefghijklmnopqrst | 723 // do identifier_abcdefghijklmnopqrst |
| 710 for (Token token = tokenize(currentText); | 724 for (Token token = tokenize('$state$line'); |
| 711 token.kind != EOF_TOKEN; | 725 token.kind != EOF_TOKEN; |
| 712 token = token.next) { | 726 token = token.next) { |
| 713 int charOffset = token.charOffset; | 727 int charOffset = token.charOffset; |
| 714 int charCount = token.charCount; | 728 int charCount = token.charCount; |
| 715 | 729 |
| 716 if (charOffset < offset) continue; // Happens for scanner errors. | 730 Token tokenToDecorate = token; |
| 731 if (token is UnterminatedToken && isUnterminatedMultiLineToken(token)) { | |
| 732 newState = '$newState${token.start}'; | |
|
ahe
2014/05/02 10:01:45
Using += compiles to:
newState += t1.get$
| |
| 733 continue; // This might not be an error. | |
| 734 } else { | |
| 735 Token follow = token.next; | |
| 736 if (token is BeginGroupToken && token.endGroup != null) { | |
| 737 follow = token.endGroup.next; | |
| 738 } | |
| 739 if (follow is ErrorToken && follow.charOffset == token.charOffset) { | |
| 740 if (follow is UnmatchedToken) { | |
| 741 newState = '$newState${follow.begin.value}'; | |
|
ahe
2014/05/02 10:01:45
Compiles to:
newState += H.S(t1.get$v
| |
| 742 } else { | |
| 743 tokenToDecorate = follow; | |
| 744 } | |
| 745 } | |
| 746 } | |
| 717 | 747 |
| 718 Decoration decoration = editor.getDecoration(token); | 748 if (charOffset < offset) { |
| 749 // Happens for scanner errors, or for the [state] prefix. | |
| 750 continue; | |
| 751 } | |
| 719 | 752 |
| 720 Token follow = token.next; | 753 Decoration decoration = editor.getDecoration(tokenToDecorate); |
| 721 if (token is BeginGroupToken) { | |
| 722 follow = token.endGroup.next; | |
| 723 } | |
| 724 if (follow is ErrorToken) { | |
| 725 decoration = editor.getDecoration(follow); | |
| 726 } | |
| 727 | 754 |
| 728 if (decoration == null) continue; | 755 if (decoration == null) continue; |
| 729 | 756 |
| 730 // Add a node for text before current token. | 757 // Add a node for text before current token. |
| 731 trySelection.addNodeFromSubstring(offset, charOffset, nodes); | 758 trySelection.addNodeFromSubstring( |
|
kasperl
2014/05/02 08:01:06
Compue (start - state.length) only once?
ahe
2014/05/02 10:01:45
Done.
| |
| 759 start + offset - state.length, start + charOffset - state.length, | |
| 760 nodes); | |
| 732 | 761 |
| 733 // Add a node for current token. | 762 // Add a node for current token. |
| 734 trySelection.addNodeFromSubstring( | 763 trySelection.addNodeFromSubstring( |
| 735 charOffset, charOffset + charCount, nodes, decoration); | 764 start + charOffset - state.length, |
| 765 start + charOffset + charCount - state.length, nodes, decoration); | |
| 736 | 766 |
| 737 offset = charOffset + charCount; | 767 offset = charOffset + charCount; |
| 738 } | 768 } |
| 739 | 769 |
| 740 // Add a node for anything after the last (decorated) token. | 770 // Add a node for anything after the last (decorated) token. |
| 741 trySelection.addNodeFromSubstring(offset, currentText.length, nodes); | 771 trySelection.addNodeFromSubstring( |
| 772 start + offset - state.length, start + line.length, nodes); | |
| 742 | 773 |
| 743 // Ensure text always ends with a newline. | 774 return newState; |
| 744 if (!currentText.endsWith('\n')) { | 775 } |
| 745 nodes.add(new Text('\n')); | 776 |
| 746 } | 777 bool isUnterminatedMultiLineToken(UnterminatedToken token) { |
| 778 return | |
| 779 token.start == '/*' || | |
| 780 token.start == "'''" || | |
| 781 token.start == '"""' || | |
| 782 token.start == "r'''" || | |
| 783 token.start == 'r"""'; | |
| 747 } | 784 } |
| 748 | 785 |
| 749 void normalizeMutationRecord(MutationRecord record, TrySelection selection) { | 786 void normalizeMutationRecord(MutationRecord record, TrySelection selection) { |
| 750 if (record.addedNodes.isEmpty) return; | 787 if (record.addedNodes.isEmpty) return; |
| 751 for (Node node in record.addedNodes) { | 788 for (Node node in record.addedNodes) { |
| 752 if (node.parent == null) continue; | 789 if (node.parent == null) continue; |
| 753 StringBuffer buffer = new StringBuffer(); | 790 StringBuffer buffer = new StringBuffer(); |
| 754 int selectionOffset = htmlToText(node, buffer, selection); | 791 int selectionOffset = htmlToText(node, buffer, selection); |
| 755 Text newNode = new Text('$buffer'); | 792 Text newNode = new Text('$buffer'); |
| 756 node.replaceWith(newNode); | 793 node.replaceWith(newNode); |
| 757 if (selectionOffset != -1) { | 794 if (selectionOffset != -1) { |
| 758 selection.anchorNode = newNode; | 795 selection.anchorNode = newNode; |
| 759 selection.anchorOffset = selectionOffset; | 796 selection.anchorOffset = selectionOffset; |
| 760 } | 797 } |
| 761 } | 798 } |
| 762 } | 799 } |
| OLD | NEW |