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

Unified Diff: pkg/analysis_server/lib/src/get_handler.dart

Issue 759083003: Allow the contents of the analysis cache to be inspected via html debugging. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/engine.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analysis_server/lib/src/get_handler.dart
diff --git a/pkg/analysis_server/lib/src/get_handler.dart b/pkg/analysis_server/lib/src/get_handler.dart
index f457ddcd07cd0e6d5b5c818cbfa0400c86ce749b..96a000b1e034867e670ae1c9b263cfd138541dff 100644
--- a/pkg/analysis_server/lib/src/get_handler.dart
+++ b/pkg/analysis_server/lib/src/get_handler.dart
@@ -28,9 +28,10 @@ class GetHandler {
static const String STATUS_PATH = '/status';
/**
- * The path used to request code completion information.
+ * The path used to request information about the cache entry corresponding
+ * to a single file.
*/
- static const String COMPLETION_PATH = '/completion';
+ static const String CACHE_ENTRY_PATH = '/cache_entry';
/**
* The path used to request the list of source files in a certain cache
@@ -39,6 +40,11 @@ class GetHandler {
static const String CACHE_STATE_PATH = '/cache_state';
/**
+ * The path used to request code completion information.
+ */
+ static const String COMPLETION_PATH = '/completion';
+
+ /**
* Query parameter used to represent the cache state to search for, when
* accessing [CACHE_STATE_PATH].
*/
@@ -46,7 +52,7 @@ class GetHandler {
/**
* Query parameter used to represent the context to search for, when
- * accessing [CACHE_STATE_PATH].
+ * accessing [CACHE_ENTRY_PATH] or [CACHE_STATE_PATH].
*/
static const String CONTEXT_QUERY_PARAM = 'context';
@@ -57,6 +63,12 @@ class GetHandler {
static const String DESCRIPTOR_QUERY_PARAM = 'descriptor';
/**
+ * Query parameter used to represent the source to search for, when accessing
+ * [CACHE_ENTRY_PATH].
+ */
+ static const String SOURCE_QUERY_PARAM = 'entry';
+
+ /**
* The socket server whose status is to be reported on.
*/
SocketServer _server;
@@ -80,6 +92,8 @@ class GetHandler {
_returnServerStatus(request);
} else if (path == CACHE_STATE_PATH) {
_returnCacheState(request);
+ } else if (path == CACHE_ENTRY_PATH) {
+ _returnCacheEntry(request);
} else if (path == COMPLETION_PATH) {
_returnCompletionInfo(request);
} else {
@@ -97,6 +111,132 @@ class GetHandler {
}
/**
+ * Generate a table showing the cache values corresponding to the given
+ * [descriptors], using [getState] to get the cache state corresponding to
+ * each descriptor, and [getValue] to get the cached value corresponding to
+ * each descriptor. Append the resulting HTML to [response].
+ */
+ void _outputDescriptorTable(HttpResponse response,
+ List<DataDescriptor> descriptors, CacheState getState(DataDescriptor), dynamic
+ getValue(DataDescriptor)) {
+ response.write('<dl>');
+ for (DataDescriptor descriptor in descriptors) {
+ String descriptorName = HTML_ESCAPE.convert(descriptor.toString());
+ String descriptorState =
+ HTML_ESCAPE.convert(getState(descriptor).toString());
+ response.write('<dt>$descriptorName ($descriptorState)</dt><dd>');
+ try {
+ _outputValueAsHtml(response, getValue(descriptor));
+ } catch (exception) {
+ response.write('(${HTML_ESCAPE.convert(exception.toString())})');
+ }
+ response.write('</dd>');
+ }
+ response.write('</dl>');
+ }
+
+ /**
+ * Render the given [value] as HTML and append it to [response].
+ */
+ void _outputValueAsHtml(HttpResponse response, dynamic value) {
+ if (value == null) {
+ response.write('<i>null</i>');
+ } else if (value is String) {
+ response.write('<pre>${HTML_ESCAPE.convert(value)}</pre>');
+ } else if (value is List) {
+ response.write('${value.length} entries');
+ response.write('<ul>');
+ for (var entry in value) {
+ response.write('<li>');
+ _outputValueAsHtml(response, entry);
+ response.write('</li>');
+ }
+ response.write('</ul>');
+ } else {
+ response.write(HTML_ESCAPE.convert(value.toString()));
+ response.write(
+ ' <i>(${HTML_ESCAPE.convert(value.runtimeType.toString())})</i>');
+ }
+ }
+
+ /**
+ * Return a response containing information about a single source file in the
+ * cache.
+ */
+ void _returnCacheEntry(HttpRequest request) {
+ // Figure out which context is being searched for.
+ String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
+ if (contextFilter == null) {
+ return _returnFailure(
+ request,
+ 'Query parameter $CONTEXT_QUERY_PARAM required');
+ }
+
+ // Figure out which CacheEntry is being searched for.
+ String sourceUri = request.uri.queryParameters[SOURCE_QUERY_PARAM];
+ if (sourceUri == null) {
+ return _returnFailure(
+ request,
+ 'Query parameter $SOURCE_QUERY_PARAM required');
+ }
+
+ AnalysisServer analysisServer = _server.analysisServer;
+ if (analysisServer == null) {
+ return _returnFailure(request, 'Analysis server not running');
+ }
+ HttpResponse response = request.response;
+ response.statusCode = HttpStatus.OK;
+ response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html");
+ response.write('<html>');
+ response.write('<head>');
+ response.write('<title>Dart Analysis Server - Search result</title>');
+ response.write('</head>');
+ response.write('<body>');
+ response.write('<h1>');
+ response.write('File ${HTML_ESCAPE.convert(sourceUri)}');
+ response.write(' in context ${HTML_ESCAPE.convert(contextFilter)}');
+ response.write('</h1>');
+ analysisServer.folderMap.forEach(
+ (Folder folder, AnalysisContextImpl context) {
+ if (folder.path != contextFilter) {
+ return;
+ }
+ Source source = context.sourceFactory.forUri(sourceUri);
+ if (source == null) {
+ response.write('<p>Not found.</p>');
+ return;
+ }
+ SourceEntry entry = context.getReadableSourceEntryOrNull(source);
+ if (entry == null) {
+ response.write('<p>Not found.</p>');
+ return;
+ }
+ response.write('<h2>File info:</h2><dl>');
+ _outputDescriptorTable(
+ response,
+ entry.descriptors,
+ entry.getState,
+ entry.getValue);
+ if (entry is DartEntry) {
+ for (Source librarySource in entry.containingLibraries) {
+ String libraryName = HTML_ESCAPE.convert(librarySource.fullName);
+ response.write('<h2>In library $libraryName:</h2>');
+ _outputDescriptorTable(
+ response,
+ entry.libraryDescriptors,
+ (DataDescriptor descriptor) =>
+ entry.getStateInLibrary(descriptor, librarySource),
+ (DataDescriptor descriptor) =>
+ entry.getValueInLibrary(descriptor, librarySource));
+ }
+ }
+ });
+ response.write('</body>');
+ response.write('</html>');
+ response.close();
+ }
+
+ /**
* Return a response indicating the set of source files in a certain cache
* state.
*/
@@ -167,7 +307,11 @@ class GetHandler {
if (state != stateFilter || rowDesc.toString() != descriptorFilter) {
return;
}
- response.write('<li>${HTML_ESCAPE.convert(source.fullName)}</li>');
+ String link = _makeLink(CACHE_ENTRY_PATH, {
+ CONTEXT_QUERY_PARAM: folder.path,
+ SOURCE_QUERY_PARAM: source.uri.toString()
+ }, HTML_ESCAPE.convert(source.fullName));
+ response.write('<li>$link</li>');
count++;
});
});
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698