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

Side by Side Diff: pkg/analysis_server/lib/src/status/diagnostics.dart

Issue 2981123002: add env var info to the diagnostics page (Closed)
Patch Set: Created 3 years, 5 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
« no previous file with comments | « no previous file | no next file » | 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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 import 'dart:async'; 5 import 'dart:async';
6 import 'dart:convert'; 6 import 'dart:convert';
7 import 'dart:io'; 7 import 'dart:io';
8 8
9 import 'package:analysis_server/protocol/protocol_generated.dart'; 9 import 'package:analysis_server/protocol/protocol_generated.dart';
10 import 'package:analysis_server/src/analysis_server.dart'; 10 import 'package:analysis_server/src/analysis_server.dart';
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 104
105 .menu-item .counter { 105 .menu-item .counter {
106 float: right; 106 float: right;
107 margin-left: 5px; 107 margin-left: 5px;
108 } 108 }
109 109
110 td.right { 110 td.right {
111 text-align: right; 111 text-align: right;
112 } 112 }
113 113
114 table td {
115 max-width: 600px;
116 vertical-align: text-top;
117 }
118
114 td.pre { 119 td.pre {
115 white-space: pre; 120 white-space: pre;
116 } 121 }
117 122
118 .nowrap { 123 .nowrap {
119 white-space: nowrap; 124 white-space: nowrap;
120 } 125 }
121 126
122 .scroll-table { 127 .scroll-table {
123 max-height: 190px; 128 max-height: 190px;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 return; 175 return;
171 } 176 }
172 AnalysisDriver driver = server.getAnalysisDriver(path); 177 AnalysisDriver driver = server.getAnalysisDriver(path);
173 if (driver == null) { 178 if (driver == null) {
174 p('The file <code>${escape(path)}</code> is not being analyzed.', 179 p('The file <code>${escape(path)}</code> is not being analyzed.',
175 raw: true); 180 raw: true);
176 return; 181 return;
177 } 182 }
178 AnalysisResult result = await driver.getResult(path); 183 AnalysisResult result = await driver.getResult(path);
179 if (result == null) { 184 if (result == null) {
180 p('An AST could not be produced for the file <code>${escape(path)}</code>. ', 185 p(
186 'An AST could not be produced for the file <code>${escape(
187 path)}</code>.',
181 raw: true); 188 raw: true);
182 return; 189 return;
183 } 190 }
184 191
185 AstWriter writer = new AstWriter(buf); 192 AstWriter writer = new AstWriter(buf);
186 result.unit.accept(writer); 193 result.unit.accept(writer);
187 } 194 }
188 195
189 @override 196 @override
190 Future<Null> generatePage(Map<String, String> params) async { 197 Future<Null> generatePage(Map<String, String> params) async {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 List<CompletionPerformance> completions = 306 List<CompletionPerformance> completions =
300 completionDomain.performanceList.items.toList(); 307 completionDomain.performanceList.items.toList();
301 308
302 if (completions.isEmpty) { 309 if (completions.isEmpty) {
303 blankslate('No completions recorded.'); 310 blankslate('No completions recorded.');
304 return; 311 return;
305 } 312 }
306 313
307 int fastCount = 314 int fastCount =
308 completions.where((c) => c.elapsedInMilliseconds <= 100).length; 315 completions.where((c) => c.elapsedInMilliseconds <= 100).length;
309 p('${completions.length} results; ${printPercentage(fastCount / completions. length)} within 100ms.'); 316 p('${completions.length} results; ${printPercentage(
317 fastCount / completions.length)} within 100ms.');
310 318
311 // draw a chart 319 // draw a chart
312 buf.writeln( 320 buf.writeln(
313 '<div id="chart-div" style="width: 700px; height: 300px;"></div>'); 321 '<div id="chart-div" style="width: 700px; height: 300px;"></div>');
314 StringBuffer rowData = new StringBuffer(); 322 StringBuffer rowData = new StringBuffer();
315 for (int i = completions.length - 1; i >= 0; i--) { 323 for (int i = completions.length - 1; i >= 0; i--) {
316 // [' ', 101.5] 324 // [' ', 101.5]
317 if (rowData.isNotEmpty) { 325 if (rowData.isNotEmpty) {
318 rowData.write(','); 326 rowData.write(',');
319 } 327 }
(...skipping 14 matching lines...) Expand all
334 } 342 }
335 </script> 343 </script>
336 '''); 344 ''');
337 345
338 // emit the data as a table 346 // emit the data as a table
339 buf.writeln('<table>'); 347 buf.writeln('<table>');
340 buf.writeln( 348 buf.writeln(
341 '<tr><th>Time</th><th>Results</th><th>Source</th><th>Snippet</th></tr>') ; 349 '<tr><th>Time</th><th>Results</th><th>Source</th><th>Snippet</th></tr>') ;
342 for (CompletionPerformance completion in completions) { 350 for (CompletionPerformance completion in completions) {
343 buf.writeln('<tr>' 351 buf.writeln('<tr>'
344 '<td class="pre right">${printMilliseconds(completion.elapsedInMillise conds)}</td>' 352 '<td class="pre right">${printMilliseconds(
353 completion.elapsedInMilliseconds)}</td>'
345 '<td class="right">${completion.suggestionCount}</td>' 354 '<td class="right">${completion.suggestionCount}</td>'
346 '<td>${escape(completion.source.shortName)}</td>' 355 '<td>${escape(completion.source.shortName)}</td>'
347 '<td><code>${escape(completion.snippet)}</code></td>' 356 '<td><code>${escape(completion.snippet)}</code></td>'
348 '</tr>'); 357 '</tr>');
349 } 358 }
350 buf.writeln('</table>'); 359 buf.writeln('</table>');
351 } 360 }
352 } 361 }
353 362
354 class ContextsPage extends DiagnosticPageWithNav { 363 class ContextsPage extends DiagnosticPageWithNav {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 .join(', ')); 467 .join(', '));
459 468
460 List<String> priorityFiles = driver.priorityFiles; 469 List<String> priorityFiles = driver.priorityFiles;
461 List<String> addedFiles = driver.addedFiles.toList(); 470 List<String> addedFiles = driver.addedFiles.toList();
462 List<String> implicitFiles = 471 List<String> implicitFiles =
463 driver.knownFiles.difference(driver.addedFiles).toList(); 472 driver.knownFiles.difference(driver.addedFiles).toList();
464 addedFiles.sort(); 473 addedFiles.sort();
465 implicitFiles.sort(); 474 implicitFiles.sort();
466 475
467 String lenCounter(List list) { 476 String lenCounter(List list) {
468 return '<span class="counter" style="float: right;">${list.length}</span>' ; 477 return '<span class="counter" style="float: right;">${list
478 .length}</span>';
469 } 479 }
470 480
471 h3('Context files'); 481 h3('Context files');
472 482
473 void writeFile(String file) { 483 void writeFile(String file) {
474 String astPath = '/ast?file=${Uri.encodeQueryComponent(file)}'; 484 String astPath = '/ast?file=${Uri.encodeQueryComponent(file)}';
475 String elementPath = '/element?file=${Uri.encodeQueryComponent(file)}'; 485 String elementPath = '/element?file=${Uri.encodeQueryComponent(file)}';
476 486
477 buf.write(file); 487 buf.write(file);
478 buf.writeln(' <a href="$astPath">ast</a>'); 488 buf.writeln(' <a href="$astPath">ast</a>');
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 buf.writeln(''' 595 buf.writeln('''
586 <header class="masthead"> 596 <header class="masthead">
587 <div class="container"> 597 <div class="container">
588 <span class="masthead-logo"> 598 <span class="masthead-logo">
589 <span class="mega-octicon octicon-dashboard"></span> 599 <span class="mega-octicon octicon-dashboard"></span>
590 ${site.title} Diagnostics 600 ${site.title} Diagnostics
591 </span> 601 </span>
592 602
593 <nav class="masthead-nav"> 603 <nav class="masthead-nav">
594 <a href="/status" ${isNavPage ? ' class="active"' : ''}>Diagnostics</a> 604 <a href="/status" ${isNavPage ? ' class="active"' : ''}>Diagnostics</a>
595 <a href="/feedback" ${isCurrentPage('/feedback') ? ' class="active"' : ' '}>Feedback</a> 605 <a href="/feedback" ${isCurrentPage('/feedback')
606 ? ' class="active"'
607 : ''}>Feedback</a>
596 <a href="https://www.dartlang.org/tools/analyzer" target="_blank">Docs</ a> 608 <a href="https://www.dartlang.org/tools/analyzer" target="_blank">Docs</ a>
597 <a href="https://htmlpreview.github.io/?https://github.com/dart-lang/sdk /blob/master/pkg/analysis_server/doc/api.html" target="_blank">Spec</a> 609 <a href="https://htmlpreview.github.io/?https://github.com/dart-lang/sdk /blob/master/pkg/analysis_server/doc/api.html" target="_blank">Spec</a>
598 </nav> 610 </nav>
599 </div> 611 </div>
600 </header> 612 </header>
601 '''); 613 ''');
602 } 614 }
603 615
604 Future<Null> generatePage(Map<String, String> params) async { 616 Future<Null> generatePage(Map<String, String> params) async {
605 buf.writeln('<!DOCTYPE html><html lang="en">'); 617 buf.writeln('<!DOCTYPE html><html lang="en">');
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 SocketServer socketServer; 690 SocketServer socketServer;
679 691
680 /// The last few lines printed. 692 /// The last few lines printed.
681 List<String> lastPrintedLines = <String>[]; 693 List<String> lastPrintedLines = <String>[];
682 694
683 DiagnosticsSite(this.socketServer, this.lastPrintedLines) 695 DiagnosticsSite(this.socketServer, this.lastPrintedLines)
684 : super('Analysis Server') { 696 : super('Analysis Server') {
685 pages.add(new CompletionPage(this)); 697 pages.add(new CompletionPage(this));
686 pages.add(new CommunicationsPage(this)); 698 pages.add(new CommunicationsPage(this));
687 pages.add(new ContextsPage(this)); 699 pages.add(new ContextsPage(this));
700 pages.add(new EnvironmentVariablesPage(this));
688 pages.add(new ExceptionsPage(this)); 701 pages.add(new ExceptionsPage(this));
689 pages.add(new InstrumentationPage(this)); 702 pages.add(new InstrumentationPage(this));
690 pages.add(new OverlaysPage(this)); 703 pages.add(new OverlaysPage(this));
691 pages.add(new PluginsPage(this)); 704 pages.add(new PluginsPage(this));
692 pages.add(new ProfilePage(this)); 705 pages.add(new ProfilePage(this));
693 pages.add(new SubscriptionsPage(this)); 706 pages.add(new SubscriptionsPage(this));
694 707
695 ProcessProfiler profiler = ProcessProfiler.getProfilerForPlatform(); 708 ProcessProfiler profiler = ProcessProfiler.getProfilerForPlatform();
696 if (profiler != null) { 709 if (profiler != null) {
697 pages.add(new MemoryAndCpuPage(this, profiler)); 710 pages.add(new MemoryAndCpuPage(this, profiler));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 return; 752 return;
740 } 753 }
741 AnalysisDriver driver = server.getAnalysisDriver(path); 754 AnalysisDriver driver = server.getAnalysisDriver(path);
742 if (driver == null) { 755 if (driver == null) {
743 p('The file <code>${escape(path)}</code> is not being analyzed.', 756 p('The file <code>${escape(path)}</code> is not being analyzed.',
744 raw: true); 757 raw: true);
745 return; 758 return;
746 } 759 }
747 AnalysisResult result = await driver.getResult(path); 760 AnalysisResult result = await driver.getResult(path);
748 if (result == null) { 761 if (result == null) {
749 p('An element model could not be produced for the file <code>${escape(path )}</code>.', 762 p(
763 'An element model could not be produced for the file <code>${escape(
764 path)}</code>.',
750 raw: true); 765 raw: true);
751 return; 766 return;
752 } 767 }
753 768
754 ElementWriter writer = new ElementWriter(buf); 769 ElementWriter writer = new ElementWriter(buf);
755 result.unit.element.accept(writer); 770 result.unit.element.accept(writer);
756 } 771 }
757 772
758 @override 773 @override
759 Future<Null> generatePage(Map<String, String> params) async { 774 Future<Null> generatePage(Map<String, String> params) async {
(...skipping 10 matching lines...) Expand all
770 final StackTrace trace; 785 final StackTrace trace;
771 786
772 ExceptionPage(Site site, String message, this.trace) 787 ExceptionPage(Site site, String message, this.trace)
773 : super(site, '', '500 Oops', description: message); 788 : super(site, '', '500 Oops', description: message);
774 789
775 void generateContent(Map<String, String> params) { 790 void generateContent(Map<String, String> params) {
776 p(trace.toString(), style: 'white-space: pre'); 791 p(trace.toString(), style: 'white-space: pre');
777 } 792 }
778 } 793 }
779 794
795 class EnvironmentVariablesPage extends DiagnosticPageWithNav {
796 EnvironmentVariablesPage(DiagnosticsSite site)
797 : super(site, 'environment', 'Environment Variables',
798 description:
799 'System environment variables as seen from the analysis server.' );
800
801 @override
802 void generateContent(Map<String, String> params) {
803 buf.writeln('<table>');
804 buf.writeln('<tr><th>Variable</th><th>Value</th></tr>');
805 for (String key in Platform.environment.keys.toList()..sort()) {
806 String value = Platform.environment[key];
807 buf.writeln('<tr><td>${escape(key)}</td><td>${escape(value)}</td></tr>');
808 }
809 buf.writeln('</table>');
810 }
811 }
812
780 class ExceptionsPage extends DiagnosticPageWithNav { 813 class ExceptionsPage extends DiagnosticPageWithNav {
781 ExceptionsPage(DiagnosticsSite site) 814 ExceptionsPage(DiagnosticsSite site)
782 : super(site, 'exceptions', 'Exceptions', 815 : super(site, 'exceptions', 'Exceptions',
783 description: 'Exceptions from the analysis server.'); 816 description: 'Exceptions from the analysis server.');
784 817
785 Iterable<ServerException> get exceptions => server.exceptions.items; 818 Iterable<ServerException> get exceptions => server.exceptions.items;
786 819
787 String get navDetail => printInteger(exceptions.length); 820 String get navDetail => printInteger(exceptions.length);
788 821
789 @override 822 @override
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 if (server.options.clientId != null) { 859 if (server.options.clientId != null) {
827 ideInfo.add(server.options.clientId); 860 ideInfo.add(server.options.clientId);
828 } 861 }
829 if (server.options.clientVersion != null) { 862 if (server.options.clientVersion != null) {
830 ideInfo.add(server.options.clientVersion); 863 ideInfo.add(server.options.clientVersion);
831 } 864 }
832 String ideText = ideInfo.map((str) => '<code>$str</code>').join(', '); 865 String ideText = ideInfo.map((str) => '<code>$str</code>').join(', ');
833 866
834 p('Other data to include:'); 867 p('Other data to include:');
835 ul([ 868 ul([
836 "the IDE you are using and it's version${ideText.isEmpty ? '' : ' ($ideTex t)'}", 869 "the IDE you are using and it's version${ideText.isEmpty
870 ? ''
871 : ' ($ideText)'}",
837 'the Dart SDK version (<code>${escape(_sdkVersion)}</code>)', 872 'the Dart SDK version (<code>${escape(_sdkVersion)}</code>)',
838 'your operating system (<code>${escape(Platform.operatingSystem)}</code>)' , 873 'your operating system (<code>${escape(
874 Platform.operatingSystem)}</code>)',
839 ], (line) => buf.writeln(line)); 875 ], (line) => buf.writeln(line));
840 876
841 p('Thanks!'); 877 p('Thanks!');
842 } 878 }
843 } 879 }
844 880
845 class InstrumentationPage extends DiagnosticPageWithNav { 881 class InstrumentationPage extends DiagnosticPageWithNav {
846 InstrumentationPage(DiagnosticsSite site) 882 InstrumentationPage(DiagnosticsSite site)
847 : super(site, 'instrumentation', 'Instrumentation', 883 : super(site, 'instrumentation', 'Instrumentation',
848 description: 884 description:
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 p('<code>${escape(overlayPath)}</code> not found.', raw: true); 971 p('<code>${escape(overlayPath)}</code> not found.', raw: true);
936 } 972 }
937 973
938 return; 974 return;
939 } 975 }
940 976
941 if (paths.isEmpty) { 977 if (paths.isEmpty) {
942 blankslate('No overlays.'); 978 blankslate('No overlays.');
943 } else { 979 } else {
944 String lenCounter(List list) { 980 String lenCounter(List list) {
945 return '<span class="counter" style="float: right;">${list.length}</span >'; 981 return '<span class="counter" style="float: right;">${list
982 .length}</span>';
946 } 983 }
947 984
948 h3('Overlays ${lenCounter(paths)}', raw: true); 985 h3('Overlays ${lenCounter(paths)}', raw: true);
949 ul(paths, (String overlayPath) { 986 ul(paths, (String overlayPath) {
950 String uri = '$path?overlay=${Uri.encodeQueryComponent(overlayPath)}'; 987 String uri = '$path?overlay=${Uri.encodeQueryComponent(overlayPath)}';
951 buf.writeln('<a href="$uri">${escape(overlayPath)}</a>'); 988 buf.writeln('<a href="$uri">${escape(overlayPath)}</a>');
952 }); 989 });
953 } 990 }
954 } 991 }
955 } 992 }
(...skipping 25 matching lines...) Expand all
981 1018
982 List<Plugin> plugins = [ 1019 List<Plugin> plugins = [
983 AnalysisEngine.instance.enginePlugin, 1020 AnalysisEngine.instance.enginePlugin,
984 server.serverPlugin 1021 server.serverPlugin
985 ]; 1022 ];
986 plugins.addAll(server.userDefinedPlugins); 1023 plugins.addAll(server.userDefinedPlugins);
987 ul(plugins, writePlugin); 1024 ul(plugins, writePlugin);
988 } 1025 }
989 } 1026 }
990 1027
1028 // TODO(devoncarew): We're not currently tracking the time spent in specific
1029 // lints by default (analysisOptions / driverOptions enableTiming)
1030 final bool _showLints = false;
Brian Wilkerson 2017/07/19 21:51:09 It would be nice to be able to see the timing info
devoncarew 2017/07/19 22:02:13 I don't think it's ever enabled in the context of
1031
991 class ProfilePage extends DiagnosticPageWithNav { 1032 class ProfilePage extends DiagnosticPageWithNav {
992 ProfilePage(DiagnosticsSite site) 1033 ProfilePage(DiagnosticsSite site)
993 : super(site, 'profile', 'Profiling Info', 1034 : super(site, 'profile', 'Profiling Info',
994 description: 'Profiling performance tag data and lint timings.'); 1035 description: 'Profiling performance tag data.');
995 1036
996 @override 1037 @override
997 void generateContent(Map<String, String> params) { 1038 void generateContent(Map<String, String> params) {
998 h3('Profiling performance tag data'); 1039 h3('Profiling performance tag data');
999 1040
1000 // prepare sorted tags 1041 // prepare sorted tags
1001 List<PerformanceTag> tags = PerformanceTag.all.toList(); 1042 List<PerformanceTag> tags = PerformanceTag.all.toList();
1002 tags.remove(ServerPerformanceStatistics.idle); 1043 tags.remove(ServerPerformanceStatistics.idle);
1003 tags.remove(PerformanceTag.unknown); 1044 tags.remove(PerformanceTag.unknown);
1004 tags.removeWhere((tag) => tag.elapsedMs == 0); 1045 tags.removeWhere((tag) => tag.elapsedMs == 0);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 _writeRow([ 1096 _writeRow([
1056 tag.label, 1097 tag.label,
1057 printMilliseconds(tag.elapsedMs), 1098 printMilliseconds(tag.elapsedMs),
1058 printPercentage(percent) 1099 printPercentage(percent)
1059 ]); 1100 ]);
1060 } 1101 }
1061 1102
1062 tags.forEach(writeRow); 1103 tags.forEach(writeRow);
1063 buf.write('</table>'); 1104 buf.write('</table>');
1064 1105
1065 h3('Lint rule timings'); 1106 if (_showLints) {
1066 List<LintRule> rules = Registry.ruleRegistry.rules.toList(); 1107 h3('Lint rule timings');
1067 int totalLintTime = rules.fold(0, 1108 List<LintRule> rules = Registry.ruleRegistry.rules.toList();
1068 (sum, rule) => sum + lintRegistry.getTimer(rule).elapsedMilliseconds); 1109 int totalLintTime = rules.fold(0,
1069 p('Total time spent in lints: ${printMilliseconds(totalLintTime)}'); 1110 (sum, rule) => sum + lintRegistry.getTimer(rule).elapsedMilliseconds);
1111 p('Total time spent in lints: ${printMilliseconds(totalLintTime)}');
1070 1112
1071 rules.sort((first, second) { 1113 rules.sort((first, second) {
1072 int firstTime = lintRegistry.getTimer(first).elapsedMilliseconds; 1114 int firstTime = lintRegistry.getTimer(first).elapsedMilliseconds;
1073 int secondTime = lintRegistry.getTimer(second).elapsedMilliseconds; 1115 int secondTime = lintRegistry.getTimer(second).elapsedMilliseconds;
1074 if (firstTime == secondTime) { 1116 if (firstTime == secondTime) {
1075 return first.lintCode.name.compareTo(second.lintCode.name); 1117 return first.lintCode.name.compareTo(second.lintCode.name);
1118 }
1119 return secondTime - firstTime;
1120 });
1121 buf.write('<table>');
1122 _writeRow(['Lint code', 'Time (in ms)'], header: true);
1123 for (var rule in rules) {
1124 int time = lintRegistry.getTimer(rule).elapsedMilliseconds;
1125 _writeRow([rule.lintCode.name, printMilliseconds(time)]);
1076 } 1126 }
1077 return secondTime - firstTime; 1127 buf.write('</table>');
1078 });
1079 buf.write('<table>');
1080 _writeRow(['Lint code', 'Time (in ms)'], header: true);
1081 for (var rule in rules) {
1082 int time = lintRegistry.getTimer(rule).elapsedMilliseconds;
1083 _writeRow([rule.lintCode.name, printMilliseconds(time)]);
1084 } 1128 }
1085 buf.write('</table>');
1086 } 1129 }
1087 } 1130 }
1088 1131
1089 class StatusPage extends DiagnosticPageWithNav { 1132 class StatusPage extends DiagnosticPageWithNav {
1090 StatusPage(DiagnosticsSite site) 1133 StatusPage(DiagnosticsSite site)
1091 : super(site, 'status', 'Status', 1134 : super(site, 'status', 'Status',
1092 description: 1135 description:
1093 'General status and diagnostics for the analysis server.'); 1136 'General status and diagnostics for the analysis server.');
1094 1137
1095 @override 1138 @override
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 h3('Execution domain'); 1196 h3('Execution domain');
1154 ul(ExecutionService.VALUES, (item) { 1197 ul(ExecutionService.VALUES, (item) {
1155 if (domain.onFileAnalyzed != null) { 1198 if (domain.onFileAnalyzed != null) {
1156 buf.write('$item (has subscriptions)'); 1199 buf.write('$item (has subscriptions)');
1157 } else { 1200 } else {
1158 buf.write('$item (no subscriptions)'); 1201 buf.write('$item (no subscriptions)');
1159 } 1202 }
1160 }); 1203 });
1161 } 1204 }
1162 } 1205 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698