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 analysis_server.src.status.get_handler; | 5 library analysis_server.src.status.get_handler; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:io'; | 10 import 'dart:io'; |
11 import 'dart:math'; | 11 import 'dart:math'; |
12 | 12 |
13 import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element; | 13 import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element; |
14 import 'package:analysis_server/src/analysis_server.dart'; | 14 import 'package:analysis_server/src/analysis_server.dart'; |
15 import 'package:analysis_server/src/domain_completion.dart'; | 15 import 'package:analysis_server/src/domain_completion.dart'; |
16 import 'package:analysis_server/src/domain_diagnostic.dart'; | 16 import 'package:analysis_server/src/domain_diagnostic.dart'; |
17 import 'package:analysis_server/src/domain_execution.dart'; | 17 import 'package:analysis_server/src/domain_execution.dart'; |
18 import 'package:analysis_server/src/operation/operation.dart'; | 18 import 'package:analysis_server/src/operation/operation.dart'; |
19 import 'package:analysis_server/src/operation/operation_analysis.dart'; | 19 import 'package:analysis_server/src/operation/operation_analysis.dart'; |
20 import 'package:analysis_server/src/operation/operation_queue.dart'; | 20 import 'package:analysis_server/src/operation/operation_queue.dart'; |
21 import 'package:analysis_server/src/services/index/index.dart'; | 21 import 'package:analysis_server/src/services/index/index.dart'; |
22 import 'package:analysis_server/src/services/index/local_index.dart'; | 22 import 'package:analysis_server/src/services/index/local_index.dart'; |
23 import 'package:analysis_server/src/services/index/store/split_store.dart'; | 23 import 'package:analysis_server/src/services/index/store/split_store.dart'; |
24 import 'package:analysis_server/src/socket_server.dart'; | 24 import 'package:analysis_server/src/socket_server.dart'; |
25 import 'package:analysis_server/src/status/ast_writer.dart'; | 25 import 'package:analysis_server/src/status/ast_writer.dart'; |
26 import 'package:analysis_server/src/status/element_writer.dart'; | 26 import 'package:analysis_server/src/status/element_writer.dart'; |
27 import 'package:analysis_server/src/status/validator.dart'; | |
27 import 'package:analysis_server/src/utilities/average.dart'; | 28 import 'package:analysis_server/src/utilities/average.dart'; |
28 import 'package:analyzer/file_system/file_system.dart'; | 29 import 'package:analyzer/file_system/file_system.dart'; |
29 import 'package:analyzer/src/context/cache.dart'; | 30 import 'package:analyzer/src/context/cache.dart'; |
30 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl; | 31 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl; |
31 import 'package:analyzer/src/generated/ast.dart'; | 32 import 'package:analyzer/src/generated/ast.dart'; |
32 import 'package:analyzer/src/generated/element.dart'; | 33 import 'package:analyzer/src/generated/element.dart'; |
33 import 'package:analyzer/src/generated/engine.dart' | 34 import 'package:analyzer/src/generated/engine.dart' |
34 hide AnalysisCache, AnalysisContextImpl, AnalysisTask; | 35 hide AnalysisCache, AnalysisContextImpl, AnalysisTask; |
35 import 'package:analyzer/src/generated/error.dart'; | 36 import 'package:analyzer/src/generated/error.dart'; |
36 import 'package:analyzer/src/generated/java_engine.dart'; | 37 import 'package:analyzer/src/generated/java_engine.dart'; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 * The path used to request code completion information. | 87 * The path used to request code completion information. |
87 */ | 88 */ |
88 static const String COMPLETION_PATH = '/completion'; | 89 static const String COMPLETION_PATH = '/completion'; |
89 | 90 |
90 /** | 91 /** |
91 * The path used to request communication performance information. | 92 * The path used to request communication performance information. |
92 */ | 93 */ |
93 static const String COMMUNICATION_PERFORMANCE_PATH = '/perf/communication'; | 94 static const String COMMUNICATION_PERFORMANCE_PATH = '/perf/communication'; |
94 | 95 |
95 /** | 96 /** |
97 * The path used to request diagnostic information for a single context. | |
98 */ | |
99 static const String CONTEXT_DIAGNOSTICS_PATH = '/diagnostic/context'; | |
100 | |
101 /** | |
102 * The path used to request running a validation report for a single context. | |
103 */ | |
104 static const String CONTEXT_VALIDATION_DIAGNOSTICS_PATH = | |
105 '/diagnostic/contextValidation'; | |
106 | |
107 /** | |
96 * The path used to request information about a specific context. | 108 * The path used to request information about a specific context. |
97 */ | 109 */ |
98 static const String CONTEXT_PATH = '/context'; | 110 static const String CONTEXT_PATH = '/context'; |
99 | 111 |
100 /** | 112 /** |
101 * The path used to request diagnostic information. | 113 * The path used to request diagnostic information. |
102 */ | 114 */ |
103 static const String DIAGNOSTIC_PATH = '/diagnostic'; | 115 static const String DIAGNOSTIC_PATH = '/diagnostic'; |
104 | 116 |
105 /** | 117 /** |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 } | 226 } |
215 return analysisServer.handlers | 227 return analysisServer.handlers |
216 .firstWhere((h) => h is CompletionDomainHandler, orElse: () => null); | 228 .firstWhere((h) => h is CompletionDomainHandler, orElse: () => null); |
217 } | 229 } |
218 | 230 |
219 /** | 231 /** |
220 * Handle a GET request received by the HTTP server. | 232 * Handle a GET request received by the HTTP server. |
221 */ | 233 */ |
222 void handleGetRequest(HttpRequest request) { | 234 void handleGetRequest(HttpRequest request) { |
223 String path = request.uri.path; | 235 String path = request.uri.path; |
224 if (path == STATUS_PATH) { | 236 if (path == '/' || path == STATUS_PATH) { |
225 _returnServerStatus(request); | 237 _returnServerStatus(request); |
226 } else if (path == ANALYSIS_PERFORMANCE_PATH) { | 238 } else if (path == ANALYSIS_PERFORMANCE_PATH) { |
227 _returnAnalysisPerformance(request); | 239 _returnAnalysisPerformance(request); |
228 } else if (path == AST_PATH) { | 240 } else if (path == AST_PATH) { |
229 _returnAst(request); | 241 _returnAst(request); |
230 } else if (path == CACHE_STATE_PATH) { | 242 } else if (path == CACHE_STATE_PATH) { |
231 _returnCacheState(request); | 243 _returnCacheState(request); |
232 } else if (path == CACHE_ENTRY_PATH) { | 244 } else if (path == CACHE_ENTRY_PATH) { |
233 _returnCacheEntry(request); | 245 _returnCacheEntry(request); |
234 } else if (path == COMPLETION_PATH) { | 246 } else if (path == COMPLETION_PATH) { |
235 _returnCompletionInfo(request); | 247 _returnCompletionInfo(request); |
236 } else if (path == COMMUNICATION_PERFORMANCE_PATH) { | 248 } else if (path == COMMUNICATION_PERFORMANCE_PATH) { |
237 _returnCommunicationPerformance(request); | 249 _returnCommunicationPerformance(request); |
250 } else if (path == CONTEXT_DIAGNOSTICS_PATH) { | |
251 _returnContextDiagnostics(request); | |
252 } else if (path == CONTEXT_VALIDATION_DIAGNOSTICS_PATH) { | |
253 _returnContextValidationDiagnostics(request); | |
238 } else if (path == CONTEXT_PATH) { | 254 } else if (path == CONTEXT_PATH) { |
239 _returnContextInfo(request); | 255 _returnContextInfo(request); |
240 } else if (path == DIAGNOSTIC_PATH) { | 256 } else if (path == DIAGNOSTIC_PATH) { |
241 _returnDiagnosticInfo(request); | 257 _returnDiagnosticInfo(request); |
242 } else if (path == ELEMENT_PATH) { | 258 } else if (path == ELEMENT_PATH) { |
243 _returnElement(request); | 259 _returnElement(request); |
244 } else if (path == INDEX_ELEMENT_BY_NAME) { | 260 } else if (path == INDEX_ELEMENT_BY_NAME) { |
245 _returnIndexElementByName(request); | 261 _returnIndexElementByName(request); |
246 } else if (path == OVERLAY_PATH) { | 262 } else if (path == OVERLAY_PATH) { |
247 _returnOverlayContents(request); | 263 _returnOverlayContents(request); |
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
966 _writeResponse(request, (StringBuffer buffer) { | 982 _writeResponse(request, (StringBuffer buffer) { |
967 _writePage(buffer, 'Analysis Server - Completion Stats', [], | 983 _writePage(buffer, 'Analysis Server - Completion Stats', [], |
968 (StringBuffer buffer) { | 984 (StringBuffer buffer) { |
969 _writeCompletionPerformanceDetail(buffer, index); | 985 _writeCompletionPerformanceDetail(buffer, index); |
970 _writeCompletionPerformanceList(buffer); | 986 _writeCompletionPerformanceList(buffer); |
971 }); | 987 }); |
972 }); | 988 }); |
973 } | 989 } |
974 | 990 |
975 /** | 991 /** |
992 * Return a response displaying diagnostic information for a single context. | |
993 */ | |
994 void _returnContextDiagnostics(HttpRequest request) { | |
995 AnalysisServer analysisServer = _server.analysisServer; | |
996 if (analysisServer == null) { | |
997 return _returnFailure(request, 'Analysis server is not running'); | |
998 } | |
999 String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM]; | |
1000 if (contextFilter == null) { | |
1001 return _returnFailure( | |
1002 request, 'Query parameter $CONTEXT_QUERY_PARAM required'); | |
1003 } | |
1004 Folder folder = _findFolder(analysisServer, contextFilter); | |
1005 if (folder == null) { | |
1006 return _returnFailure(request, 'Invalid context: $contextFilter'); | |
1007 } | |
1008 | |
1009 InternalAnalysisContext context = analysisServer.folderMap[folder]; | |
1010 | |
1011 _writeResponse(request, (StringBuffer buffer) { | |
1012 _writePage(buffer, 'Analysis Server - Context Diagnostics', | |
1013 ['Context: $contextFilter'], (StringBuffer buffer) { | |
1014 _writeContextDiagnostics(buffer, context); | |
1015 }); | |
1016 }); | |
1017 } | |
1018 | |
1019 /** | |
976 * Return a response containing information about a single source file in the | 1020 * Return a response containing information about a single source file in the |
977 * cache. | 1021 * cache. |
978 */ | 1022 */ |
979 void _returnContextInfo(HttpRequest request) { | 1023 void _returnContextInfo(HttpRequest request) { |
980 AnalysisServer analysisServer = _server.analysisServer; | 1024 AnalysisServer analysisServer = _server.analysisServer; |
981 if (analysisServer == null) { | 1025 if (analysisServer == null) { |
982 return _returnFailure(request, 'Analysis server not running'); | 1026 return _returnFailure(request, 'Analysis server not running'); |
983 } | 1027 } |
984 String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM]; | 1028 String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM]; |
985 if (contextFilter == null) { | 1029 if (contextFilter == null) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1025 } else { | 1069 } else { |
1026 implicitNames.add(sourceName); | 1070 implicitNames.add(sourceName); |
1027 } | 1071 } |
1028 links[sourceName] = link; | 1072 links[sourceName] = link; |
1029 } | 1073 } |
1030 } | 1074 } |
1031 } | 1075 } |
1032 explicitNames.sort(); | 1076 explicitNames.sort(); |
1033 implicitNames.sort(); | 1077 implicitNames.sort(); |
1034 | 1078 |
1035 AnalysisDriver driver = (context as AnalysisContextImpl).driver; | |
1036 List<WorkItem> workItems = driver.currentWorkOrder?.workItems; | |
1037 | |
1038 _overlayContents.clear(); | 1079 _overlayContents.clear(); |
1039 context.visitContentCache((String fullName, int stamp, String contents) { | 1080 context.visitContentCache((String fullName, int stamp, String contents) { |
1040 _overlayContents[fullName] = contents; | 1081 _overlayContents[fullName] = contents; |
1041 }); | 1082 }); |
1042 | 1083 |
1043 void _writeFiles( | 1084 void _writeFiles( |
1044 StringBuffer buffer, String title, List<String> fileNames) { | 1085 StringBuffer buffer, String title, List<String> fileNames) { |
1045 buffer.write('<h3>$title</h3>'); | 1086 buffer.write('<h3>$title</h3>'); |
1046 if (fileNames == null || fileNames.isEmpty) { | 1087 if (fileNames == null || fileNames.isEmpty) { |
1047 buffer.write('<p>None</p>'); | 1088 buffer.write('<p>None</p>'); |
(...skipping 10 matching lines...) Expand all Loading... | |
1058 buffer.write('</td></tr>'); | 1099 buffer.write('</td></tr>'); |
1059 } | 1100 } |
1060 buffer.write('</table></p>'); | 1101 buffer.write('</table></p>'); |
1061 } | 1102 } |
1062 } | 1103 } |
1063 | 1104 |
1064 _writeResponse(request, (StringBuffer buffer) { | 1105 _writeResponse(request, (StringBuffer buffer) { |
1065 _writePage( | 1106 _writePage( |
1066 buffer, 'Analysis Server - Context', ['Context: $contextFilter'], | 1107 buffer, 'Analysis Server - Context', ['Context: $contextFilter'], |
1067 (StringBuffer buffer) { | 1108 (StringBuffer buffer) { |
1068 buffer.write('<h3>Most Recently Perfomed Tasks</h3>'); | |
1069 AnalysisTask.LAST_TASKS.forEach((String description) { | |
1070 buffer.write('<p>$description</p>'); | |
1071 }); | |
1072 | |
1073 String _describe(WorkItem item) { | |
1074 if (item == null) { | |
1075 return 'None'; | |
1076 } | |
1077 return '${item.descriptor?.name} computing ${item.spawningResult?.name } for ${item.target?.toString()}'; | |
1078 } | |
1079 | |
1080 buffer.write('<h3>Work Items</h3>'); | |
1081 buffer.write( | |
1082 '<p><b>Current:</b> ${_describe(driver.currentWorkOrder?.current)}</ p>'); | |
1083 if (workItems != null) { | |
1084 buffer.writeAll(workItems.reversed | |
1085 .map((item) => '<p>${_describe(item)}</p>') | |
1086 ?.toList()); | |
1087 } | |
1088 | |
1089 buffer.write('<h3>Configuration</h3>'); | 1109 buffer.write('<h3>Configuration</h3>'); |
1090 | 1110 |
1091 AnalysisOptionsImpl options = context.analysisOptions; | 1111 _writeTwoColumns(buffer, (StringBuffer buffer) { |
1092 buffer.write('<p><b>Options</b></p>'); | 1112 AnalysisOptionsImpl options = context.analysisOptions; |
1093 buffer.write('<p>'); | 1113 buffer.write('<p><b>Options</b></p>'); |
1094 _writeOption( | 1114 buffer.write('<p>'); |
1095 buffer, 'Analyze functon bodies', options.analyzeFunctionBodies); | 1115 _writeOption( |
1096 _writeOption(buffer, 'Cache size', options.cacheSize); | 1116 buffer, 'Analyze functon bodies', options.analyzeFunctionBodies); |
1097 _writeOption( | 1117 _writeOption(buffer, 'Cache size', options.cacheSize); |
1098 buffer, 'Enable generic methods', options.enableGenericMethods); | 1118 _writeOption( |
1099 _writeOption(buffer, 'Enable strict call checks', | 1119 buffer, 'Enable generic methods', options.enableGenericMethods); |
1100 options.enableStrictCallChecks); | 1120 _writeOption(buffer, 'Enable strict call checks', |
1101 _writeOption(buffer, 'Enable super mixins', options.enableSuperMixins); | 1121 options.enableStrictCallChecks); |
1102 _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint); | 1122 _writeOption( |
1103 _writeOption(buffer, 'Generate errors in implicit files', | 1123 buffer, 'Enable super mixins', options.enableSuperMixins); |
1104 options.generateImplicitErrors); | 1124 _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint); |
1105 _writeOption( | 1125 _writeOption(buffer, 'Generate errors in implicit files', |
1106 buffer, 'Generate errors in SDK files', options.generateSdkErrors); | 1126 options.generateImplicitErrors); |
1107 _writeOption(buffer, 'Generate hints', options.hint); | 1127 _writeOption(buffer, 'Generate errors in SDK files', |
1108 _writeOption(buffer, 'Incremental resolution', options.incremental); | 1128 options.generateSdkErrors); |
1109 _writeOption(buffer, 'Incremental resolution with API changes', | 1129 _writeOption(buffer, 'Generate hints', options.hint); |
1110 options.incrementalApi); | 1130 _writeOption(buffer, 'Incremental resolution', options.incremental); |
1111 _writeOption(buffer, 'Preserve comments', options.preserveComments); | 1131 _writeOption(buffer, 'Incremental resolution with API changes', |
1112 _writeOption(buffer, 'Strong mode', options.strongMode); | 1132 options.incrementalApi); |
1113 _writeOption(buffer, 'Strong mode hints', options.strongModeHints, | 1133 _writeOption(buffer, 'Preserve comments', options.preserveComments); |
1114 last: true); | 1134 _writeOption(buffer, 'Strong mode', options.strongMode); |
1115 buffer.write('</p>'); | 1135 _writeOption(buffer, 'Strong mode hints', options.strongModeHints, |
1136 last: true); | |
1137 buffer.write('</p>'); | |
1138 }, (StringBuffer buffer) { | |
1139 List<Linter> lints = | |
1140 context.getConfigurationData(CONFIGURED_LINTS_KEY); | |
1141 buffer.write('<p><b>Lints</b></p>'); | |
1142 if (lints.isEmpty) { | |
1143 buffer.write('<p>none</p>'); | |
1144 } else { | |
1145 for (Linter lint in lints) { | |
1146 buffer.write('<p>'); | |
1147 buffer.write(lint.runtimeType); | |
1148 buffer.write('</p>'); | |
1149 } | |
1150 } | |
1116 | 1151 |
1117 List<Linter> lints = context.getConfigurationData(CONFIGURED_LINTS_KEY); | 1152 List<ErrorFilter> errorFilters = |
1118 buffer.write('<p><b>Lints</b></p>'); | 1153 context.getConfigurationData(CONFIGURED_ERROR_FILTERS); |
1119 if (lints.isEmpty) { | 1154 int filterCount = errorFilters?.length ?? 0; |
1120 buffer.write('<p><none></p>'); | 1155 buffer.write('<p><b>Error Filter count</b>: $filterCount</p>'); |
1121 } else { | 1156 }); |
1122 for (Linter lint in lints) { | |
1123 buffer.write('<p> ${lint.runtimeType}</p>'); | |
1124 } | |
1125 } | |
1126 | |
1127 List<ErrorFilter> errorFilters = | |
1128 context.getConfigurationData(CONFIGURED_ERROR_FILTERS); | |
1129 int filterCount = errorFilters?.length ?? 0; | |
1130 buffer.write('<p><b>Error Filter count</b>: $filterCount</p>'); | |
1131 | 1157 |
1132 _writeFiles(buffer, 'Priority Files', priorityNames); | 1158 _writeFiles(buffer, 'Priority Files', priorityNames); |
1133 _writeFiles(buffer, 'Explicitly Analyzed Files', explicitNames); | 1159 _writeFiles(buffer, 'Explicitly Analyzed Files', explicitNames); |
1134 _writeFiles(buffer, 'Implicitly Analyzed Files', implicitNames); | 1160 _writeFiles(buffer, 'Implicitly Analyzed Files', implicitNames); |
1135 | 1161 |
1136 buffer.write('<h3>Exceptions</h3>'); | 1162 buffer.write('<h3>Exceptions</h3>'); |
1137 if (exceptions.isEmpty) { | 1163 if (exceptions.isEmpty) { |
1138 buffer.write('<p>None</p>'); | 1164 buffer.write('<p>none</p>'); |
1139 } else { | 1165 } else { |
1140 exceptions.forEach((CaughtException exception) { | 1166 exceptions.forEach((CaughtException exception) { |
1141 _writeException(buffer, exception); | 1167 _writeException(buffer, exception); |
1142 }); | 1168 }); |
1143 } | 1169 } |
1170 | |
1171 buffer.write('<h3>Targets Without Entries</h3>'); | |
1172 bool foundEntry = false; | |
1173 MapIterator<AnalysisTarget, CacheEntry> iterator = | |
1174 context.analysisCache.iterator(context: context); | |
1175 while (iterator.moveNext()) { | |
1176 if (iterator.value == null) { | |
1177 foundEntry = true; | |
1178 buffer.write('<p>'); | |
1179 buffer.write(iterator.key.toString()); | |
scheglov
2015/12/07 06:19:29
The runtimeType is also interesting.
Brian Wilkerson
2015/12/07 16:03:25
Done
| |
1180 buffer.write('</p>'); | |
1181 } | |
1182 } | |
1183 if (!foundEntry) { | |
1184 buffer.write('<p>none</p>'); | |
1185 } | |
1144 }); | 1186 }); |
1145 }); | 1187 }); |
1146 } | 1188 } |
1189 | |
1190 /** | |
1191 * Return a response displaying the results of running a validation report on | |
1192 * a single context. | |
1193 */ | |
1194 void _returnContextValidationDiagnostics(HttpRequest request) { | |
1195 AnalysisServer analysisServer = _server.analysisServer; | |
1196 if (analysisServer == null) { | |
1197 return _returnFailure(request, 'Analysis server is not running'); | |
1198 } | |
1199 String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM]; | |
1200 if (contextFilter == null) { | |
1201 return _returnFailure( | |
1202 request, 'Query parameter $CONTEXT_QUERY_PARAM required'); | |
1203 } | |
1204 Folder folder = _findFolder(analysisServer, contextFilter); | |
1205 if (folder == null) { | |
1206 return _returnFailure(request, 'Invalid context: $contextFilter'); | |
1207 } | |
1208 | |
1209 InternalAnalysisContext context = analysisServer.folderMap[folder]; | |
1210 | |
1211 _writeResponse(request, (StringBuffer buffer) { | |
1212 _writePage(buffer, 'Analysis Server - Context Validation Diagnostics', | |
1213 ['Context: $contextFilter'], (StringBuffer buffer) { | |
1214 _writeContextValidationDiagnostics(buffer, context); | |
1215 }); | |
1216 }); | |
1217 } | |
1147 | 1218 |
1148 /** | 1219 /** |
1149 * Return a response displaying diagnostic information. | 1220 * Return a response displaying diagnostic information. |
1150 */ | 1221 */ |
1151 void _returnDiagnosticInfo(HttpRequest request) { | 1222 void _returnDiagnosticInfo(HttpRequest request) { |
1152 String value = request.requestedUri.queryParameters['index']; | |
1153 int index = value != null ? int.parse(value, onError: (_) => 0) : 0; | |
1154 _writeResponse(request, (StringBuffer buffer) { | 1223 _writeResponse(request, (StringBuffer buffer) { |
1155 _writePage(buffer, 'Analysis Server - Diagnostic info', [], | 1224 _writePage(buffer, 'Analysis Server - Diagnostic info', [], |
1156 (StringBuffer buffer) { | 1225 (StringBuffer buffer) { |
1157 _writeDiagnosticStatus(buffer); | 1226 _writeDiagnosticStatus(buffer); |
1158 }); | 1227 }); |
1159 }); | 1228 }); |
1160 } | 1229 } |
1161 | 1230 |
1162 /** | 1231 /** |
1163 * Return a response containing information about an element structure. | 1232 * Return a response containing information about an element structure. |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1325 }); | 1394 }); |
1326 } | 1395 } |
1327 | 1396 |
1328 /** | 1397 /** |
1329 * Return an error in response to an unrecognized request received by the HTTP | 1398 * Return an error in response to an unrecognized request received by the HTTP |
1330 * server. | 1399 * server. |
1331 */ | 1400 */ |
1332 void _returnUnknownRequest(HttpRequest request) { | 1401 void _returnUnknownRequest(HttpRequest request) { |
1333 _writeResponse(request, (StringBuffer buffer) { | 1402 _writeResponse(request, (StringBuffer buffer) { |
1334 _writePage(buffer, 'Analysis Server', [], (StringBuffer buffer) { | 1403 _writePage(buffer, 'Analysis Server', [], (StringBuffer buffer) { |
1335 buffer.write('<h3>Pages</h3>'); | 1404 buffer.write('<h3>Unknown page: '); |
1336 buffer.write('<p>'); | 1405 buffer.write(request.uri.path); |
1337 buffer.write(makeLink(COMPLETION_PATH, {}, 'Completion data')); | 1406 buffer.write('</h3>'); |
1338 buffer.write('</p>'); | 1407 buffer.write(''' |
1339 buffer.write('<p>'); | 1408 <p> |
1340 buffer | 1409 You have reached an un-recognized page. If you reached this page by |
1341 .write(makeLink(COMMUNICATION_PERFORMANCE_PATH, {}, 'Performance')); | 1410 following a link from a status page, please report the broken link to |
1342 buffer.write('</p>'); | 1411 the Dart analyzer team: |
1343 buffer.write('<p>'); | 1412 <a>https://github.com/dart-lang/sdk/issues/new</a>. |
1344 buffer.write(makeLink(STATUS_PATH, {}, 'Server status')); | 1413 </p><p> |
1345 buffer.write('</p>'); | 1414 If you mistyped the URL, you can correct it or return to |
1346 buffer.write('<p>'); | 1415 ${makeLink(STATUS_PATH, {}, 'the main status page')}. |
1347 buffer.write(makeLink(OVERLAYS_PATH, {}, 'File overlays')); | 1416 </p>'''); |
1348 buffer.write('</p>'); | |
1349 buffer.write('<p>'); | |
1350 buffer.write(makeLink(DIAGNOSTIC_PATH, {}, 'Diagnostic info')); | |
1351 buffer.write('</p>'); | |
1352 }); | 1417 }); |
1353 }); | 1418 }); |
1354 } | 1419 } |
1355 | 1420 |
1356 /** | 1421 /** |
1357 * Return a two digit decimal representation of the given non-negative integer | 1422 * Return a two digit decimal representation of the given non-negative integer |
1358 * [value]. | 1423 * [value]. |
1359 */ | 1424 */ |
1360 String _twoDigit(int value) { | 1425 String _twoDigit(int value) { |
1361 if (value < 10) { | 1426 if (value < 10) { |
1362 return '0$value'; | 1427 return '0$value'; |
1363 } | 1428 } |
1364 return value.toString(); | 1429 return value.toString(); |
1365 } | 1430 } |
1366 | 1431 |
1367 /** | 1432 /** |
1368 * Write the status of the analysis domain (on the main status page) to the | 1433 * Write the status of the analysis domain (on the main status page) to the |
1369 * given [buffer] object. | 1434 * given [buffer] object. |
1370 */ | 1435 */ |
1371 void _writeAnalysisStatus(StringBuffer buffer) { | 1436 void _writeAnalysisStatus(StringBuffer buffer) { |
1372 AnalysisServer analysisServer = _server.analysisServer; | 1437 AnalysisServer analysisServer = _server.analysisServer; |
1373 Map<Folder, AnalysisContext> folderMap = analysisServer.folderMap; | 1438 Map<Folder, AnalysisContext> folderMap = analysisServer.folderMap; |
1374 List<Folder> folders = folderMap.keys.toList(); | 1439 List<Folder> folders = folderMap.keys.toList(); |
1375 folders.sort((Folder first, Folder second) => | 1440 folders.sort((Folder first, Folder second) => |
1376 first.shortName.compareTo(second.shortName)); | 1441 first.shortName.compareTo(second.shortName)); |
1377 AnalysisOptionsImpl options = analysisServer.defaultContextOptions; | |
1378 ServerOperationQueue operationQueue = analysisServer.operationQueue; | 1442 ServerOperationQueue operationQueue = analysisServer.operationQueue; |
1379 | 1443 |
1380 buffer.write('<h3>Analysis Domain</h3>'); | 1444 buffer.write('<h3>Analysis Domain</h3>'); |
1381 _writeTwoColumns(buffer, (StringBuffer buffer) { | 1445 _writeTwoColumns(buffer, (StringBuffer buffer) { |
1382 if (operationQueue.isEmpty) { | 1446 if (operationQueue.isEmpty) { |
1383 buffer.write('<p>Status: Done analyzing</p>'); | 1447 buffer.write('<p>Status: Done analyzing</p>'); |
1384 } else { | 1448 } else { |
1385 ServerOperation operation = operationQueue.peek(); | 1449 ServerOperation operation = operationQueue.peek(); |
1386 if (operation is PerformAnalysisOperation) { | 1450 if (operation is PerformAnalysisOperation) { |
1387 Folder folder = _keyForValue(folderMap, operation.context); | 1451 Folder folder = _keyForValue(folderMap, operation.context); |
1388 if (folder == null) { | 1452 if (folder == null) { |
1389 buffer.write('<p>Status: Analyzing in unmapped context</p>'); | 1453 buffer.write('<p>Status: Analyzing in unmapped context</p>'); |
1390 } else { | 1454 } else { |
1391 buffer.write('<p>Status: Analyzing in ${folder.path}</p>'); | 1455 buffer.write('<p>Status: Analyzing in ${folder.path}</p>'); |
1392 } | 1456 } |
1393 } else { | 1457 } else { |
1394 buffer.write('<p>Status: Analyzing</p>'); | 1458 buffer.write('<p>Status: Analyzing</p>'); |
1395 } | 1459 } |
1396 } | 1460 } |
1461 buffer.write('<p>'); | |
1462 buffer.write(makeLink(OVERLAYS_PATH, {}, 'All overlay information')); | |
1463 buffer.write('</p>'); | |
1397 | 1464 |
1398 buffer.write('<p><b>Analysis Contexts</b></p>'); | 1465 buffer.write('<p><b>Analysis Contexts</b></p>'); |
1399 buffer.write('<p>'); | 1466 buffer.write('<p>'); |
1400 bool first = true; | 1467 bool first = true; |
1401 folders.forEach((Folder folder) { | 1468 folders.forEach((Folder folder) { |
1402 if (first) { | 1469 if (first) { |
1403 first = false; | 1470 first = false; |
1404 } else { | 1471 } else { |
1405 buffer.write('<br>'); | 1472 buffer.write('<br>'); |
1406 } | 1473 } |
1407 String key = folder.shortName; | 1474 String key = folder.shortName; |
1408 buffer.write(makeLink(CONTEXT_PATH, {CONTEXT_QUERY_PARAM: folder.path}, | 1475 buffer.write(makeLink(CONTEXT_PATH, {CONTEXT_QUERY_PARAM: folder.path}, |
1409 key, _hasException(folderMap[folder]))); | 1476 key, _hasException(folderMap[folder]))); |
1477 buffer.write(' <small><b>['); | |
1478 buffer.write(makeLink(CONTEXT_DIAGNOSTICS_PATH, | |
1479 {CONTEXT_QUERY_PARAM: folder.path}, 'diagnostics')); | |
1480 buffer.write(']</b></small>'); | |
1410 if (!folder.getChild('.packages').exists) { | 1481 if (!folder.getChild('.packages').exists) { |
1411 buffer.write(' <b>[No .packages file]</b>'); | 1482 buffer.write(' <small>[no .packages file]</small>'); |
1412 } | 1483 } |
1413 }); | 1484 }); |
1414 // TODO(brianwilkerson) Add items for the SDK contexts (currently only one ). | 1485 // TODO(brianwilkerson) Add items for the SDK contexts (currently only one ). |
1415 buffer.write('</p>'); | 1486 buffer.write('</p>'); |
1416 | 1487 |
1417 int freq = AnalysisServer.performOperationDelayFreqency; | 1488 int freq = AnalysisServer.performOperationDelayFreqency; |
1418 String delay = freq > 0 ? '1 ms every $freq ms' : 'off'; | 1489 String delay = freq > 0 ? '1 ms every $freq ms' : 'off'; |
1419 buffer.write('<p><b>perform operation delay:</b> $delay</p>'); | |
1420 | 1490 |
1421 buffer.write('<p><b>Performance Data</b></p>'); | 1491 buffer.write('<p><b>Performance Data</b></p>'); |
1492 buffer.write('<p>Perform operation delay: $delay</p>'); | |
1422 buffer.write('<p>'); | 1493 buffer.write('<p>'); |
1423 buffer.write(makeLink(ANALYSIS_PERFORMANCE_PATH, {}, 'Task data')); | 1494 buffer.write(makeLink(ANALYSIS_PERFORMANCE_PATH, {}, 'Task data')); |
1424 buffer.write('</p>'); | 1495 buffer.write('</p>'); |
1425 }, (StringBuffer buffer) { | 1496 }, (StringBuffer buffer) { |
1426 _writeSubscriptionMap( | 1497 _writeSubscriptionMap( |
1427 buffer, AnalysisService.VALUES, analysisServer.analysisServices); | 1498 buffer, AnalysisService.VALUES, analysisServer.analysisServices); |
1428 }); | 1499 }); |
1429 } | 1500 } |
1430 | 1501 |
1431 /** | 1502 /** |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1524 <p><strong># Notifications</strong> - the total number of notifications | 1595 <p><strong># Notifications</strong> - the total number of notifications |
1525 sent to the client with completion results for this request. | 1596 sent to the client with completion results for this request. |
1526 <p><strong># Suggestions</strong> - the number of suggestions | 1597 <p><strong># Suggestions</strong> - the number of suggestions |
1527 sent to the client in the first notification, followed by a comma, | 1598 sent to the client in the first notification, followed by a comma, |
1528 followed by the number of suggestions send to the client | 1599 followed by the number of suggestions send to the client |
1529 in the last notification. If there is only one notification, | 1600 in the last notification. If there is only one notification, |
1530 then there will be only one number in this column.'''); | 1601 then there will be only one number in this column.'''); |
1531 } | 1602 } |
1532 | 1603 |
1533 /** | 1604 /** |
1605 * Write diagnostic information about the given [context] to the given | |
1606 * [buffer]. | |
1607 */ | |
1608 void _writeContextDiagnostics( | |
1609 StringBuffer buffer, InternalAnalysisContext context) { | |
1610 AnalysisDriver driver = (context as AnalysisContextImpl).driver; | |
1611 List<WorkItem> workItems = driver.currentWorkOrder?.workItems; | |
1612 | |
1613 buffer.write('<p>'); | |
1614 buffer.write(makeLink(CONTEXT_VALIDATION_DIAGNOSTICS_PATH, | |
1615 {CONTEXT_QUERY_PARAM: context.name}, 'Run validation')); | |
1616 buffer.write('</p>'); | |
1617 | |
1618 buffer.write('<h3>Most Recently Perfomed Tasks</h3>'); | |
1619 AnalysisTask.LAST_TASKS.forEach((String description) { | |
1620 buffer.write('<p>'); | |
1621 buffer.write(description); | |
1622 buffer.write('</p>'); | |
1623 }); | |
1624 | |
1625 void writeWorkItem(StringBuffer buffer, WorkItem item) { | |
1626 if (item == null) { | |
1627 buffer.write('none'); | |
1628 } else { | |
1629 buffer.write(item.descriptor?.name); | |
1630 buffer.write(' computing '); | |
1631 buffer.write(item.spawningResult?.name); | |
1632 buffer.write(' for '); | |
1633 buffer.write(item.target); | |
1634 } | |
1635 } | |
1636 | |
1637 buffer.write('<h3>Work Items</h3>'); | |
1638 buffer.write('<p><b>Current:</b> '); | |
1639 writeWorkItem(buffer, driver.currentWorkOrder?.current); | |
1640 buffer.write('</p>'); | |
1641 if (workItems != null) { | |
1642 workItems.reversed.forEach((WorkItem item) { | |
1643 buffer.write('<p>'); | |
1644 writeWorkItem(buffer, item); | |
1645 buffer.write('</p>'); | |
1646 }); | |
1647 } | |
1648 } | |
1649 | |
1650 /** | |
1651 * Write diagnostic information about the given [context] to the given | |
1652 * [buffer]. | |
1653 */ | |
1654 void _writeContextValidationDiagnostics( | |
1655 StringBuffer buffer, InternalAnalysisContext context) { | |
1656 Stopwatch stopwatch = new Stopwatch(); | |
1657 stopwatch.start(); | |
1658 ValidationResults results = new ValidationResults(context); | |
1659 stopwatch.stop(); | |
1660 | |
1661 buffer.write('<h3>Validation Results</h3>'); | |
1662 buffer.write('<p>Re-analysis took '); | |
1663 buffer.write(stopwatch.elapsedMilliseconds); | |
1664 buffer.write(' ms</p>'); | |
1665 results.writeOn(buffer); | |
1666 } | |
1667 | |
1668 /** | |
1534 * Write the status of the diagnostic domain to the given [buffer]. | 1669 * Write the status of the diagnostic domain to the given [buffer]. |
1535 */ | 1670 */ |
1536 void _writeDiagnosticStatus(StringBuffer buffer) { | 1671 void _writeDiagnosticStatus(StringBuffer buffer) { |
1537 var request = new DiagnosticGetDiagnosticsParams().toRequest('0'); | 1672 var request = new DiagnosticGetDiagnosticsParams().toRequest('0'); |
1538 | 1673 |
1539 var stopwatch = new Stopwatch(); | 1674 var stopwatch = new Stopwatch(); |
1540 stopwatch.start(); | 1675 stopwatch.start(); |
1541 var response = diagnosticHandler.handleRequest(request); | 1676 var response = diagnosticHandler.handleRequest(request); |
1542 stopwatch.stop(); | 1677 stopwatch.stop(); |
1543 | 1678 |
1544 int elapsedMs = stopwatch.elapsedMilliseconds; | 1679 int elapsedMs = stopwatch.elapsedMilliseconds; |
1545 _diagnosticCallAverage.addSample(elapsedMs); | 1680 _diagnosticCallAverage.addSample(elapsedMs); |
1546 | 1681 |
1547 buffer.write('<h3>Timing</h3>'); | 1682 buffer.write('<h3>Timing</h3>'); |
1548 | 1683 |
1549 buffer.write('<p>'); | 1684 buffer.write('<p>getDiagnostic (last call): '); |
1550 buffer.write('getDiagnostic (last call): $elapsedMs (ms)'); | 1685 buffer.write(elapsedMs); |
1551 buffer.write('<p>'); | 1686 buffer.write(' (ms)</p>'); |
1552 buffer.write('getDiagnostic (rolling average): ' | 1687 buffer.write('<p>getDiagnostic (rolling average): '); |
1553 '${_diagnosticCallAverage.value} (ms)'); | 1688 buffer.write(_diagnosticCallAverage.value); |
1554 buffer.write('<p> '); | 1689 buffer.write(' (ms)</p> '); |
1555 | 1690 |
1556 var json = response.toJson()[Response.RESULT]; | 1691 var json = response.toJson()[Response.RESULT]; |
1557 List contexts = json['contexts']; | 1692 List contexts = json['contexts']; |
1693 contexts.sort((first, second) => first['name'].compareTo(second['name'])); | |
1558 for (var context in contexts) { | 1694 for (var context in contexts) { |
1559 buffer.write('<p>'); | 1695 buffer.write('<p><h3>'); |
1560 buffer.write('<h3>${context["name"]}</h3>'); | 1696 buffer.write(context['name']); |
1561 buffer.write('<p>'); | 1697 buffer.write('</h3></p>'); |
1562 buffer.write('explicitFileCount: ${context["explicitFileCount"]}'); | 1698 buffer.write('<p>explicitFileCount: '); |
1563 buffer.write('<p>'); | 1699 buffer.write(context['explicitFileCount']); |
1564 buffer.write('implicitFileCount: ${context["implicitFileCount"]}'); | 1700 buffer.write('</p>'); |
1565 buffer.write('<p>'); | 1701 buffer.write('<p>implicitFileCount: '); |
1566 buffer.write('workItemQueueLength: ${context["workItemQueueLength"]}'); | 1702 buffer.write(context['implicitFileCount']); |
1567 buffer.write('<p>'); | 1703 buffer.write('</p>'); |
1568 buffer.write('workItemQueueLengthAverage: ' | 1704 buffer.write('<p>workItemQueueLength: '); |
1569 '${context["workItemQueueLengthAverage"]}'); | 1705 buffer.write(context['workItemQueueLength']); |
1570 buffer.write('<p> '); | 1706 buffer.write('</p>'); |
1707 buffer.write('<p>workItemQueueLengthAverage: '); | |
1708 buffer.write(context['workItemQueueLengthAverage']); | |
1709 buffer.write('</p>'); | |
1571 } | 1710 } |
1572 } | 1711 } |
1573 | 1712 |
1574 /** | 1713 /** |
1575 * Write the status of the edit domain (on the main status page) to the given | 1714 * Write the status of the edit domain (on the main status page) to the given |
1576 * [buffer]. | 1715 * [buffer]. |
1577 */ | 1716 */ |
1578 void _writeEditStatus(StringBuffer buffer) { | 1717 void _writeEditStatus(StringBuffer buffer) { |
1579 buffer.write('<h3>Edit Domain</h3>'); | 1718 buffer.write('<h3>Edit Domain</h3>'); |
1580 _writeTwoColumns(buffer, (StringBuffer buffer) { | 1719 _writeTwoColumns(buffer, (StringBuffer buffer) { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1701 buffer.write('<title>$title</title>'); | 1840 buffer.write('<title>$title</title>'); |
1702 buffer.write('<style>'); | 1841 buffer.write('<style>'); |
1703 buffer.write('a {color: #0000DD; text-decoration: none;}'); | 1842 buffer.write('a {color: #0000DD; text-decoration: none;}'); |
1704 buffer.write('a:link.error {background-color: #FFEEEE;}'); | 1843 buffer.write('a:link.error {background-color: #FFEEEE;}'); |
1705 buffer.write('a:visited.error {background-color: #FFEEEE;}'); | 1844 buffer.write('a:visited.error {background-color: #FFEEEE;}'); |
1706 buffer.write('a:hover.error {background-color: #FFEEEE;}'); | 1845 buffer.write('a:hover.error {background-color: #FFEEEE;}'); |
1707 buffer.write('a:active.error {background-color: #FFEEEE;}'); | 1846 buffer.write('a:active.error {background-color: #FFEEEE;}'); |
1708 buffer.write( | 1847 buffer.write( |
1709 'h3 {background-color: #DDDDDD; margin-top: 0em; margin-bottom: 0em;}'); | 1848 'h3 {background-color: #DDDDDD; margin-top: 0em; margin-bottom: 0em;}'); |
1710 buffer.write('p {margin-top: 0.5em; margin-bottom: 0.5em;}'); | 1849 buffer.write('p {margin-top: 0.5em; margin-bottom: 0.5em;}'); |
1850 buffer.write( | |
1851 'p.commentary {margin-top: 1em; margin-bottom: 1em; margin-left: 2em; fo nt-style: italic;}'); | |
1711 // response.write('span.error {text-decoration-line: underline; text-decorati on-color: red; text-decoration-style: wavy;}'); | 1852 // response.write('span.error {text-decoration-line: underline; text-decorati on-color: red; text-decoration-style: wavy;}'); |
1712 buffer.write( | 1853 buffer.write( |
1713 'table.column {border: 0px solid black; width: 100%; table-layout: fixed ;}'); | 1854 'table.column {border: 0px solid black; width: 100%; table-layout: fixed ;}'); |
1714 buffer.write('td.column {vertical-align: top; width: 50%;}'); | 1855 buffer.write('td.column {vertical-align: top; width: 50%;}'); |
1715 buffer.write('td.right {text-align: right;}'); | 1856 buffer.write('td.right {text-align: right;}'); |
1716 buffer.write('</style>'); | 1857 buffer.write('</style>'); |
1717 buffer.write('</head>'); | 1858 buffer.write('</head>'); |
1718 | 1859 |
1719 buffer.write('<body>'); | 1860 buffer.write('<body>'); |
1720 buffer.write( | 1861 buffer.write( |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1861 buffer.write('<br>'); | 2002 buffer.write('<br>'); |
1862 buffer.write('Process ID: '); | 2003 buffer.write('Process ID: '); |
1863 buffer.write(pid); | 2004 buffer.write(pid); |
1864 buffer.write('</p>'); | 2005 buffer.write('</p>'); |
1865 | 2006 |
1866 buffer.write('<p><b>Performance Data</b></p>'); | 2007 buffer.write('<p><b>Performance Data</b></p>'); |
1867 buffer.write('<p>'); | 2008 buffer.write('<p>'); |
1868 buffer.write(makeLink( | 2009 buffer.write(makeLink( |
1869 COMMUNICATION_PERFORMANCE_PATH, {}, 'Communication performance')); | 2010 COMMUNICATION_PERFORMANCE_PATH, {}, 'Communication performance')); |
1870 buffer.write('</p>'); | 2011 buffer.write('</p>'); |
2012 buffer.write('<p>'); | |
2013 buffer.write(makeLink(DIAGNOSTIC_PATH, {}, 'General diagnostics')); | |
2014 buffer.write('</p>'); | |
1871 }, (StringBuffer buffer) { | 2015 }, (StringBuffer buffer) { |
1872 _writeSubscriptionList(buffer, ServerService.VALUES, services); | 2016 _writeSubscriptionList(buffer, ServerService.VALUES, services); |
1873 }); | 2017 }); |
1874 return true; | 2018 return true; |
1875 } | 2019 } |
1876 | 2020 |
1877 /** | 2021 /** |
1878 * Write a representation of the given [stackTrace] to the given [buffer]. | 2022 * Write a representation of the given [stackTrace] to the given [buffer]. |
1879 */ | 2023 */ |
1880 void _writeStackTrace(StringBuffer buffer, StackTrace stackTrace) { | 2024 void _writeStackTrace(StringBuffer buffer, StackTrace stackTrace) { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2068 */ | 2212 */ |
2069 static String makeLink( | 2213 static String makeLink( |
2070 String path, Map<String, String> params, String innerHtml, | 2214 String path, Map<String, String> params, String innerHtml, |
2071 [bool hasError = false]) { | 2215 [bool hasError = false]) { |
2072 Uri uri = new Uri(path: path, queryParameters: params); | 2216 Uri uri = new Uri(path: path, queryParameters: params); |
2073 String href = HTML_ESCAPE.convert(uri.toString()); | 2217 String href = HTML_ESCAPE.convert(uri.toString()); |
2074 String classAttribute = hasError ? ' class="error"' : ''; | 2218 String classAttribute = hasError ? ' class="error"' : ''; |
2075 return '<a href="$href"$classAttribute>$innerHtml</a>'; | 2219 return '<a href="$href"$classAttribute>$innerHtml</a>'; |
2076 } | 2220 } |
2077 } | 2221 } |
OLD | NEW |