Brian Slesinsky has uploaded a new change for review.
https://gwt-review.googlesource.com/3600
Change subject: Super Dev Mode: deemphasize unused Java lines in
codeserver's UI
......................................................................
Super Dev Mode: deemphasize unused Java lines in codeserver's UI
Modified the code server to render Java files as HTML when browsing
interactively. (JavaScript debuggers continue to load the plain text.)
In the HTML, lines that make no contribution to the JavaScript according
to the source map are greyed out.
This implementation is pretty inefficient since we parse the entire
source map on every html page load, but it seems to suffice.
Change-Id: Id16bcd2287630cebf7afb8bbbe0a198b28f5ada9
---
M dev/codeserver/java/com/google/gwt/dev/codeserver/HtmlWriter.java
A dev/codeserver/java/com/google/gwt/dev/codeserver/ReverseSourceMap.java
M dev/codeserver/java/com/google/gwt/dev/codeserver/SourceHandler.java
M dev/codeserver/java/com/google/gwt/dev/codeserver/SourceMap.java
4 files changed, 125 insertions(+), 15 deletions(-)
diff --git
a/dev/codeserver/java/com/google/gwt/dev/codeserver/HtmlWriter.java
b/dev/codeserver/java/com/google/gwt/dev/codeserver/HtmlWriter.java
index 7cde2c4..ddf7db4 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/HtmlWriter.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/HtmlWriter.java
@@ -17,10 +17,12 @@
class HtmlWriter {
private static final Set<String> ALLOWED_TAGS =
Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
- "html", "head", "title", "style", "body", "pre", "span", "h1", "h2",
"a",
+ "html", "head", "title", "style",
+ "body", "h1", "h2", "h3", "h4", "h5", "h6", "a", "pre", "span",
"table", "tr", "td")));
private static final Set<String> ALLOWED_ATTS =
- Collections.unmodifiableSet(new
HashSet<String>(Arrays.asList("class=", "href=")));
+ Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
+ "class=", "href=")));
private final Writer out;
diff --git
a/dev/codeserver/java/com/google/gwt/dev/codeserver/ReverseSourceMap.java
b/dev/codeserver/java/com/google/gwt/dev/codeserver/ReverseSourceMap.java
new file mode 100644
index 0000000..d82b3e1
--- /dev/null
+++
b/dev/codeserver/java/com/google/gwt/dev/codeserver/ReverseSourceMap.java
@@ -0,0 +1,42 @@
+package com.google.gwt.dev.codeserver;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.dev.util.Util;
+import com.google.gwt.thirdparty.debugging.sourcemap.SourceMapConsumerV3;
+import
com.google.gwt.thirdparty.debugging.sourcemap.SourceMapParseException;
+
+/**
+ * A mapping from Java lines to JavaScript.
+ */
+class ReverseSourceMap {
+ private final SourceMapConsumerV3 consumer;
+
+ ReverseSourceMap(SourceMapConsumerV3 consumer) {
+ this.consumer = consumer;
+ }
+
+ /**
+ * Reads a source map from disk and parses it into an in-memory
representation.
+ * If it can't be loaded, logs an error and returns null.
+ */
+ static ReverseSourceMap load(TreeLogger logger, ModuleState moduleState)
{
+ SourceMapConsumerV3 consumer = new SourceMapConsumerV3();
+ String unparsed = Util.readFileAsString(moduleState.findSourceMap());
+ try {
+ consumer.parse(unparsed);
+ return new ReverseSourceMap(consumer);
+ } catch (SourceMapParseException e) {
+ logger.log(TreeLogger.WARN, "can't parse source map", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns true if the given line in a Java file has any corresponding
JavaScript in
+ * the GWT compiler's output.
+ */
+ boolean appearsInJavaScript(String filename, int lineNumber) {
+ // TODO: getReverseMapping() seems to be off by one (lines numbered
from zero). Why?
+ return !consumer.getReverseMapping(filename, lineNumber - 1,
-1).isEmpty();
+ }
+}
diff --git
a/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceHandler.java
b/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceHandler.java
index e24755a..d82c804 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceHandler.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceHandler.java
@@ -20,8 +20,11 @@
import com.google.gwt.dev.json.JsonArray;
import com.google.gwt.dev.json.JsonObject;
+import java.io.BufferedReader;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -83,7 +86,7 @@
sendSourceMap(moduleName, request, response);
} else if (rest.endsWith(".java")) {
- sendSourceFile(moduleName, rest, response);
+ sendSourceFile(moduleName, rest, request.getQueryString(), response);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
@@ -106,8 +109,7 @@
private void sendSourceMap(String moduleName, HttpServletRequest request,
HttpServletResponse response) throws IOException {
- ModuleState moduleState = modules.get(moduleName);
- SourceMap map = SourceMap.load(moduleState.findSourceMap());
+ SourceMap map = loadSourceMap(moduleName);
// hack: rewrite the source map so that each filename is a URL
String serverPrefix = String.format("http://%s:%d/sourcemaps/%s/",
request.getServerName(),
@@ -121,8 +123,7 @@
private void sendDirectoryListPage(String moduleName,
HttpServletResponse response)
throws IOException {
- ModuleState moduleState = modules.get(moduleName);
- SourceMap map = SourceMap.load(moduleState.findSourceMap());
+ SourceMap map = loadSourceMap(moduleName);
JsonObject config = new JsonObject();
config.put("moduleName", moduleName);
@@ -140,8 +141,7 @@
private void sendFileListPage(String moduleName, String rest,
HttpServletResponse response)
throws IOException {
- ModuleState moduleState = modules.get(moduleName);
- SourceMap map = SourceMap.load(moduleState.findSourceMap());
+ SourceMap map = loadSourceMap(moduleName);
JsonObject config = new JsonObject();
config.put("moduleName", moduleName);
@@ -150,24 +150,90 @@
for (String name : map.getSourceFilesInDirectory(rest)) {
JsonObject file = new JsonObject();
file.put("name", name);
- file.put("link", name);
+ file.put("link", name + "?html");
files.add(file);
}
config.put("files", files);
PageUtil.sendJsonAndHtml("config", config, "filelist.html", response,
logger);
}
- private void sendSourceFile(String moduleName, String rest,
HttpServletResponse response)
+ /**
+ * Sends an HTTP response containing a Java source. It will be sent as
plain text by default,
+ * or as HTML if the query string is equal to "html".
+ */
+ private void sendSourceFile(String moduleName, String sourcePath, String
query,
+ HttpServletResponse response)
throws IOException {
ModuleState moduleState = modules.get(moduleName);
- InputStream pageBytes = moduleState.openSourceFile(rest);
+ InputStream pageBytes = moduleState.openSourceFile(sourcePath);
if (pageBytes == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
- logger.log(TreeLogger.WARN, "unknown source file: " + rest);
+ logger.log(TreeLogger.WARN, "unknown source file: " + sourcePath);
return;
}
- PageUtil.sendStream("text/plain", pageBytes, response);
+ if (query != null && query.equals("html")) {
+ BufferedReader reader = new BufferedReader(new
InputStreamReader(pageBytes));
+ sendSourceFileAsHtml(moduleName, sourcePath, reader, response);
+ } else {
+ PageUtil.sendStream("text/plain", pageBytes, response);
+ }
+ }
+
+ /**
+ * Sends an HTTP response containing Java source rendered as HTML. The
lines of source
+ * that have corresponding JavaScript will be highlighted (as determined
by reading the
+ * source map).
+ */
+ private void sendSourceFileAsHtml(String moduleName, String fileName,
BufferedReader lines,
+ HttpServletResponse response) throws IOException {
+
+ ReverseSourceMap sourceMap = ReverseSourceMap.load(logger,
modules.get(moduleName));
+
+ File file = new File(fileName);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("text/html");
+
+ HtmlWriter out = new HtmlWriter(response.getWriter());
+ out.startTag("html").nl();
+ out.startTag("head").nl();
+ out.startTag("title").text(file.getName() + " (GWT Code
Server)").endTag("title").nl();
+ out.startTag("style").nl();
+ out.text(".unused { color: grey; }").nl();
+ out.text(".used { color: black; }").nl();
+ out.text(".title { margin-top: 0; }").nl();
+ out.endTag("style").nl();
+ out.endTag("head").nl();
+ out.startTag("body").nl();
+
+
out.startTag("a", "href=", ".").text(file.getParent()).endTag("a").nl();
+
out.startTag("h1", "class=", "title").text(file.getName()).endTag("h1").nl();
+
+ out.startTag("pre", "class=", "unused").nl();
+ try {
+ int lineNumber = 1;
+ for (String line = lines.readLine(); line != null; line =
lines.readLine()) {
+ if (sourceMap.appearsInJavaScript(fileName, lineNumber)) {
+
out.startTag("span", "class=", "used").text(line).endTag("span").nl();
+ } else {
+ out.text(line).nl();
+ }
+ lineNumber++;
+ }
+
+ } finally {
+ lines.close();
+ }
+ out.endTag("pre").nl();
+
+ out.endTag("body").nl();
+ out.endTag("html").nl();
+ }
+
+ private SourceMap loadSourceMap(String moduleName) {
+ ModuleState moduleState = modules.get(moduleName);
+ return SourceMap.load(moduleState.findSourceMap());
}
}
diff --git
a/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceMap.java
b/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceMap.java
index dd584b8..3c13186 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceMap.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/SourceMap.java
@@ -93,7 +93,7 @@
/**
* Returns a sorted list of all filenames in the given directory.
*/
- public List<String> getSourceFilesInDirectory(String parent) {
+ List<String> getSourceFilesInDirectory(String parent) {
if (!parent.endsWith("/")) {
throw new IllegalArgumentException("unexpected: " + parent);
}
--
To view, visit https://gwt-review.googlesource.com/3600
To unsubscribe, visit https://gwt-review.googlesource.com/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id16bcd2287630cebf7afb8bbbe0a198b28f5ada9
Gerrit-PatchSet: 1
Gerrit-Project: gwt
Gerrit-Branch: master
Gerrit-Owner: Brian Slesinsky <[email protected]>
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors
---
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.