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 |