Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Side by Side Diff: dart/site/try/src/interaction_manager.dart

Issue 340343006: Send console messages through interaction manager. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Mark comment as proper TODO. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « dart/site/try/src/compilation.dart ('k') | dart/site/try/src/ui.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 import 'shadow_root.dart' show 73 import 'shadow_root.dart' show
74 getShadowRoot, 74 getShadowRoot,
75 getText, 75 getText,
76 removeShadowRootPolyfill, 76 removeShadowRootPolyfill,
77 setShadowRoot; 77 setShadowRoot;
78 78
79 const String TRY_DART_NEW_DEFECT = 79 const String TRY_DART_NEW_DEFECT =
80 'https://code.google.com/p/dart/issues/entry' 80 'https://code.google.com/p/dart/issues/entry'
81 '?template=Try+Dart+Internal+Error'; 81 '?template=Try+Dart+Internal+Error';
82 82
83 const Duration HEARTBEAT_INTERVAL = const Duration(milliseconds: 500); 83 const Duration HEARTBEAT_INTERVAL = const Duration(milliseconds: 50);
Johnni Winther 2014/06/23 14:50:01 Add comments on these constants.
ahe 2014/06/23 15:15:54 Done.
84 84
85 const Duration SAVE_INTERVAL = const Duration(seconds: 5); 85 const Duration SAVE_INTERVAL = const Duration(seconds: 5);
86 86
87 const Duration COMPILE_INTERVAL = const Duration(seconds: 1); 87 const Duration COMPILE_INTERVAL = const Duration(seconds: 1);
88 88
89 const Duration SLOW_COMPILE = const Duration(seconds: 1);
90
89 /** 91 /**
90 * UI interaction manager for the entire application. 92 * UI interaction manager for the entire application.
91 */ 93 */
92 abstract class InteractionManager { 94 abstract class InteractionManager {
93 // Design note: All UI interactions go through one instance of this 95 // Design note: All UI interactions go through one instance of this
94 // class. This is by design. 96 // class. This is by design.
95 // 97 //
96 // Simplicity in UI is in the eye of the beholder, not the implementor. Great 98 // Simplicity in UI is in the eye of the beholder, not the implementor. Great
97 // 'natural UI' is usually achieved with substantial implementation 99 // 'natural UI' is usually achieved with substantial implementation
98 // complexity that doesn't modularize well and has nasty complicated state 100 // complexity that doesn't modularize well and has nasty complicated state
(...skipping 30 matching lines...) Expand all
129 /// Called when the user selected a new project file. 131 /// Called when the user selected a new project file.
130 void onProjectFileSelected(String projectFile); 132 void onProjectFileSelected(String projectFile);
131 133
132 /// Called when notified about a project file changed (on the server). 134 /// Called when notified about a project file changed (on the server).
133 void onProjectFileFsEvent(MessageEvent e); 135 void onProjectFileFsEvent(MessageEvent e);
134 136
135 /// Called every 500ms. 137 /// Called every 500ms.
136 void onHeartbeat(Timer timer); 138 void onHeartbeat(Timer timer);
137 139
138 /// Called by [:window.onMessage.listen:]. 140 /// Called by [:window.onMessage.listen:].
139 void onMessage(MessageEvent event); 141 void onWindowMessage(MessageEvent event);
142
143 void onCompilationFailed();
140 144
141 void onCompilationDone(); 145 void onCompilationDone();
142 146
143 /// Called when a compilation is starting, but just before sending the 147 /// Called when a compilation is starting, but just before sending the
144 /// initiating message to the compiler isolate. 148 /// initiating message to the compiler isolate.
145 void compilationStarting(); 149 void compilationStarting();
150
151 // TODO(ahe): Remove this from InteractionManager, but not from InitialState.
152 void consolePrintLine(line);
153
154 void verboseCompilerMessage(String message);
146 } 155 }
147 156
148 /** 157 /**
149 * State machine for UI interactions. 158 * State machine for UI interactions.
150 */ 159 */
151 class InteractionContext extends InteractionManager { 160 class InteractionContext extends InteractionManager {
152 InteractionState state; 161 InteractionState state;
153 162
154 final Map<String, CompilationUnit> projectFiles = <String, CompilationUnit>{}; 163 final Map<String, CompilationUnit> projectFiles = <String, CompilationUnit>{};
155 164
156 final Set<CompilationUnit> modifiedUnits = new Set<CompilationUnit>(); 165 final Set<CompilationUnit> modifiedUnits = new Set<CompilationUnit>();
157 166
158 final Queue<CompilationUnit> unitsToSave = new Queue<CompilationUnit>(); 167 final Queue<CompilationUnit> unitsToSave = new Queue<CompilationUnit>();
159 168
169 /// Tracks time since last modification of a "project" file.
160 final Stopwatch saveTimer = new Stopwatch(); 170 final Stopwatch saveTimer = new Stopwatch();
161 171
172 /// Tracks time since last modification.
162 final Stopwatch compileTimer = new Stopwatch(); 173 final Stopwatch compileTimer = new Stopwatch();
163 174
175 /// Tracks elapsed time of current compilation.
176 final Stopwatch elapsedCompilationTime = new Stopwatch();
177
164 CompilationUnit currentCompilationUnit = 178 CompilationUnit currentCompilationUnit =
165 // TODO(ahe): Don't use a fake unit. 179 // TODO(ahe): Don't use a fake unit.
166 new CompilationUnit('fake', ''); 180 new CompilationUnit('fake', '');
167 181
168 Timer heartbeat; 182 Timer heartbeat;
169 183
170 Completer<String> completeSaveOperation; 184 Completer<String> completeSaveOperation;
171 185
186 bool shouldClearConsole = false;
187
188 Element compilerConsole;
189
190 bool isFirstCompile = true;
191
172 final Set<AnchorElement> oldDiagnostics = new Set<AnchorElement>(); 192 final Set<AnchorElement> oldDiagnostics = new Set<AnchorElement>();
173 193
174 InteractionContext() 194 InteractionContext()
175 : super.internal() { 195 : super.internal() {
176 state = new InitialState(this); 196 state = new InitialState(this);
177 heartbeat = new Timer.periodic(HEARTBEAT_INTERVAL, onHeartbeat); 197 heartbeat = new Timer.periodic(HEARTBEAT_INTERVAL, onHeartbeat);
178 } 198 }
179 199
180 void onInput(Event event) => state.onInput(event); 200 void onInput(Event event) => state.onInput(event);
181 201
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 void onProjectFileSelected(String projectFile) { 242 void onProjectFileSelected(String projectFile) {
223 return state.onProjectFileSelected(projectFile); 243 return state.onProjectFileSelected(projectFile);
224 } 244 }
225 245
226 void onProjectFileFsEvent(MessageEvent e) { 246 void onProjectFileFsEvent(MessageEvent e) {
227 return state.onProjectFileFsEvent(e); 247 return state.onProjectFileFsEvent(e);
228 } 248 }
229 249
230 void onHeartbeat(Timer timer) => state.onHeartbeat(timer); 250 void onHeartbeat(Timer timer) => state.onHeartbeat(timer);
231 251
232 void onMessage(MessageEvent event) => state.onMessage(event); 252 void onWindowMessage(MessageEvent event) => state.onWindowMessage(event);
253
254 void onCompilationFailed() => state.onCompilationFailed();
233 255
234 void onCompilationDone() => state.onCompilationDone(); 256 void onCompilationDone() => state.onCompilationDone();
235 257
236 void compilationStarting() => state.compilationStarting(); 258 void compilationStarting() => state.compilationStarting();
259
260 void consolePrintLine(line) => state.consolePrintLine(line);
261
262 void verboseCompilerMessage(String message) {
263 return state.verboseCompilerMessage(message);
264 }
237 } 265 }
238 266
239 abstract class InteractionState implements InteractionManager { 267 abstract class InteractionState implements InteractionManager {
240 InteractionContext get context; 268 InteractionContext get context;
241 269
242 // TODO(ahe): Remove this. 270 // TODO(ahe): Remove this.
243 Set<AnchorElement> get oldDiagnostics { 271 Set<AnchorElement> get oldDiagnostics {
244 throw 'Use context.oldDiagnostics instead'; 272 throw 'Use context.oldDiagnostics instead';
245 } 273 }
246 274
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 saveUnits(); 547 saveUnits();
520 } 548 }
521 if (!settings.compilationPaused && 549 if (!settings.compilationPaused &&
522 context.compileTimer.elapsed > COMPILE_INTERVAL) { 550 context.compileTimer.elapsed > COMPILE_INTERVAL) {
523 if (startCompilation()) { 551 if (startCompilation()) {
524 context.compileTimer 552 context.compileTimer
525 ..stop() 553 ..stop()
526 ..reset(); 554 ..reset();
527 } 555 }
528 } 556 }
557
558 if (context.elapsedCompilationTime.elapsed > SLOW_COMPILE) {
559 if (context.compilerConsole.parent == null) {
560 outputDiv.append(context.compilerConsole);
561 }
562 }
529 } 563 }
530 564
531 void saveUnits() { 565 void saveUnits() {
532 if (context.unitsToSave.isEmpty) return; 566 if (context.unitsToSave.isEmpty) return;
533 CompilationUnit unit = context.unitsToSave.removeFirst(); 567 CompilationUnit unit = context.unitsToSave.removeFirst();
534 onError(ProgressEvent event) { 568 onError(ProgressEvent event) {
535 HttpRequest request = event.target; 569 HttpRequest request = event.target;
536 statusDiv.text = "Couldn't save '${unit.name}': ${request.responseText}"; 570 statusDiv.text = "Couldn't save '${unit.name}': ${request.responseText}";
537 context.completeSaveOperation.complete(unit.name); 571 context.completeSaveOperation.complete(unit.name);
538 } 572 }
539 new HttpRequest() 573 new HttpRequest()
540 ..open("POST", "/project/${unit.name}") 574 ..open("POST", "/project/${unit.name}")
541 ..onError.listen(onError) 575 ..onError.listen(onError)
542 ..send(unit.content); 576 ..send(unit.content);
543 void setupCompleter() { 577 void setupCompleter() {
544 context.completeSaveOperation = new Completer<String>.sync(); 578 context.completeSaveOperation = new Completer<String>.sync();
545 context.completeSaveOperation.future.then((String name) { 579 context.completeSaveOperation.future.then((String name) {
546 if (name == unit.name) { 580 if (name == unit.name) {
547 print("Saved source of '$name'"); 581 print("Saved source of '$name'");
548 saveUnits(); 582 saveUnits();
549 } else { 583 } else {
550 setupCompleter(); 584 setupCompleter();
551 } 585 }
552 }); 586 });
553 } 587 }
554 setupCompleter(); 588 setupCompleter();
555 } 589 }
556 590
557 void onMessage(MessageEvent event) { 591 void onWindowMessage(MessageEvent event) {
558 if (event.source is! WindowBase || event.source == window) { 592 if (event.source is! WindowBase || event.source == window) {
559 return onBadMessage(event); 593 return onBadMessage(event);
560 } 594 }
561 if (event.data is List) { 595 if (event.data is List) {
562 List message = event.data; 596 List message = event.data;
563 if (message.length > 0) { 597 if (message.length > 0) {
564 switch (message[0]) { 598 switch (message[0]) {
565 case 'error': 599 case 'error':
566 return onErrorMessage(message[1]['url'], message[1]['message']); 600 return onErrorMessage(message[1]['url'], message[1]['message']);
567 case 'scrollHeight': 601 case 'scrollHeight':
(...skipping 26 matching lines...) Expand all
594 } 628 }
595 629
596 void onBadMessage(MessageEvent event) { 630 void onBadMessage(MessageEvent event) {
597 window.console 631 window.console
598 ..groupCollapsed('Bad message') 632 ..groupCollapsed('Bad message')
599 ..dir(event) 633 ..dir(event)
600 ..log(event.source.runtimeType) 634 ..log(event.source.runtimeType)
601 ..groupEnd(); 635 ..groupEnd();
602 } 636 }
603 637
604 void consolePrintLine(data) { 638 void consolePrintLine(line) {
605 outputDiv.appendText('$data\n'); 639 if (context.shouldClearConsole) {
640 context.shouldClearConsole = false;
641 outputDiv.nodes.clear();
642 }
643 if (window.parent != window) {
644 // Test support.
645 // TODO(ahe): Use '/' instead of '*' when Firefox is upgraded to version
646 // 30 across build bots. Support for '/' was added in version 29, and we
647 // support the two most recent versions.
648 window.parent.postMessage('$line\n', '*');
649 }
650 outputDiv.appendText('$line\n');
651 }
652
653 void onCompilationFailed() {
606 } 654 }
607 655
608 void onCompilationDone() { 656 void onCompilationDone() {
657 context.isFirstCompile = false;
658 context.elapsedCompilationTime.stop();
659 Duration compilationDuration = context.elapsedCompilationTime.elapsed;
660 context.elapsedCompilationTime.reset();
661 print('Compilation took $compilationDuration.');
662 if (context.compilerConsole.parent != null) {
663 context.compilerConsole.remove();
664 }
609 for (AnchorElement diagnostic in context.oldDiagnostics) { 665 for (AnchorElement diagnostic in context.oldDiagnostics) {
610 if (diagnostic.parent != null) { 666 if (diagnostic.parent != null) {
611 // Problem fixed, remove the diagnostic. 667 // Problem fixed, remove the diagnostic.
612 diagnostic.replaceWith(new Text(getText(diagnostic))); 668 diagnostic.replaceWith(new Text(getText(diagnostic)));
613 } 669 }
614 } 670 }
615 context.oldDiagnostics.clear(); 671 context.oldDiagnostics.clear();
616 observer.takeRecords(); // Discard mutations. 672 observer.takeRecords(); // Discard mutations.
617 } 673 }
618 674
619 void compilationStarting() { 675 void compilationStarting() {
676 var progress = new SpanElement()
677 ..appendHtml('<i class="icon-spinner icon-spin"></i>')
678 ..appendText(' Compiling Dart program.');
679 if (settings.verboseCompiler) {
680 progress.appendText('..');
681 }
682 context.compilerConsole = new SpanElement()
683 ..append(progress)
684 ..appendText('\n');
685 context.shouldClearConsole = true;
686 context.elapsedCompilationTime
687 ..start()
688 ..reset();
689 if (context.isFirstCompile) {
690 outputDiv.append(context.compilerConsole);
691 }
620 context.oldDiagnostics 692 context.oldDiagnostics
621 ..clear() 693 ..clear()
622 ..addAll(mainEditorPane.querySelectorAll('a.diagnostic')); 694 ..addAll(mainEditorPane.querySelectorAll('a.diagnostic'));
623 } 695 }
696
697 void verboseCompilerMessage(String message) {
698 if (settings.verboseCompiler) {
699 context.compilerConsole.appendText('$message\n');
700 } else {
701 if (isCompilerStageMarker(message)) {
702 Element progress = context.compilerConsole.firstChild;
703 progress.appendText('.');
704 }
705 }
706 }
624 } 707 }
625 708
626 Future<String> getString(uri) { 709 Future<String> getString(uri) {
627 return new Future<String>.sync(() => HttpRequest.getString('$uri')); 710 return new Future<String>.sync(() => HttpRequest.getString('$uri'));
628 } 711 }
629 712
630 class PendingInputState extends InitialState { 713 class PendingInputState extends InitialState {
631 PendingInputState(InteractionContext context) 714 PendingInputState(InteractionContext context)
632 : super(context); 715 : super(context);
633 716
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 return text.split(new RegExp('^', multiLine: true)); 1146 return text.split(new RegExp('^', multiLine: true));
1064 } 1147 }
1065 1148
1066 void removeCodeCompletion() { 1149 void removeCodeCompletion() {
1067 List<Node> highlighting = 1150 List<Node> highlighting =
1068 mainEditorPane.querySelectorAll('.dart-code-completion'); 1151 mainEditorPane.querySelectorAll('.dart-code-completion');
1069 for (Element element in highlighting) { 1152 for (Element element in highlighting) {
1070 element.remove(); 1153 element.remove();
1071 } 1154 }
1072 } 1155 }
1156
1157 bool isCompilerStageMarker(String message) {
1158 return
1159 message.startsWith('Package root is ') ||
1160 message.startsWith('Compiling ') ||
1161 message == "Resolving..." ||
1162 message.startsWith('Resolved ') ||
1163 message == "Inferring types..." ||
1164 message == "Compiling..." ||
1165 message.startsWith('Compiled ');
1166 }
OLDNEW
« no previous file with comments | « dart/site/try/src/compilation.dart ('k') | dart/site/try/src/ui.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698