When showing a source code, allow to highlight some spans.
authorJan Lahoda <jlahoda@netbeans.org>
Mon, 16 Jul 2012 16:16:38 +0200
changeset 83181dc1afaf5fa
parent 830 23546c35c5a2
child 832 0aef2b581506
When showing a source code, allow to highlight some spans.
remoting/server/web/web.ui/nbproject/project.properties
remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java
remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/showCode.html
remoting/server/web/web.ui/test/org/netbeans/modules/jackpot30/backend/ui/UITest.java
     1.1 --- a/remoting/server/web/web.ui/nbproject/project.properties	Fri Jul 13 11:06:24 2012 +0200
     1.2 +++ b/remoting/server/web/web.ui/nbproject/project.properties	Mon Jul 16 16:16:38 2012 +0200
     1.3 @@ -1,5 +1,6 @@
     1.4  annotation.processing.enabled=true
     1.5  annotation.processing.enabled.in.editor=false
     1.6 +annotation.processing.processors.list=
     1.7  annotation.processing.run.all.processors=true
     1.8  annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
     1.9  application.title=web.ui
    1.10 @@ -33,10 +34,13 @@
    1.11  file.reference.org-netbeans-modules-lexer.jar=../../../../lib/org-netbeans-modules-lexer.jar
    1.12  file.reference.org-netbeans-modules-parsing-lucene.jar=../../../../lib/org-netbeans-modules-parsing-lucene.jar
    1.13  file.reference.org-openide-filesystems.jar=../../../../lib/org-openide-filesystems.jar
    1.14 +file.reference.org-openide-util.jar=../../../../lib/org-openide-util.jar
    1.15  file.reference.util-commons.jar-1=../../../ide/api/external/util-commons.jar
    1.16  file.reference.util-pojson.jar-1=../../../ide/api/external/util-pojson.jar
    1.17  includes=**
    1.18 +jar.archive.disabled=${jnlp.enabled}
    1.19  jar.compress=false
    1.20 +jar.index=${jnlp.enabled}
    1.21  javac.classpath=\
    1.22      ${libs.lucene.classpath}:\
    1.23      ${libs.jersey.classpath}:\
    1.24 @@ -50,7 +54,8 @@
    1.25      ${file.reference.util-commons.jar-1}:\
    1.26      ${file.reference.util-pojson.jar-1}:\
    1.27      ${file.reference.org-netbeans-modules-java-lexer.jar}:\
    1.28 -    ${file.reference.org-netbeans-modules-lexer.jar}
    1.29 +    ${file.reference.org-netbeans-modules-lexer.jar}:\
    1.30 +    ${file.reference.org-openide-util.jar}
    1.31  # Space-separated list of extra javac options
    1.32  javac.compilerargs=
    1.33  javac.deprecation=false
    1.34 @@ -75,6 +80,15 @@
    1.35  javadoc.use=true
    1.36  javadoc.version=false
    1.37  javadoc.windowtitle=
    1.38 +jnlp.codebase.type=no.codebase
    1.39 +jnlp.descriptor=application
    1.40 +jnlp.enabled=false
    1.41 +jnlp.mixed.code=default
    1.42 +jnlp.offline-allowed=false
    1.43 +jnlp.signed=false
    1.44 +jnlp.signing=
    1.45 +jnlp.signing.alias=
    1.46 +jnlp.signing.keystore=
    1.47  main.class=type.web.api.TypeWebApi
    1.48  manifest.file=manifest.mf
    1.49  meta.inf.dir=${src.dir}/META-INF
     2.1 --- a/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java	Fri Jul 13 11:06:24 2012 +0200
     2.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java	Mon Jul 16 16:16:38 2012 +0200
     2.3 @@ -56,6 +56,7 @@
     2.4  import java.util.List;
     2.5  import java.util.Map;
     2.6  import java.util.Map.Entry;
     2.7 +import javax.ws.rs.DefaultValue;
     2.8  import javax.ws.rs.GET;
     2.9  import javax.ws.rs.Path;
    2.10  import javax.ws.rs.Produces;
    2.11 @@ -165,49 +166,95 @@
    2.12      @GET
    2.13      @Path("/show")
    2.14      @Produces("text/html")
    2.15 -    public String show(@QueryParam("path") String segment, @QueryParam("relative") String relative) throws URISyntaxException, IOException, TemplateException {
    2.16 +    public String show(@QueryParam("path") String segment, @QueryParam("relative") String relative, @QueryParam("highlight") @DefaultValue("[]") String highlightSpec) throws URISyntaxException, IOException, TemplateException {
    2.17          URI u = new URI(URL_BASE + "/source/cat?path=" + escapeForQuery(segment) + "&relative=" + escapeForQuery(relative));
    2.18          String content = WebUtilities.requestStringResponse(u);
    2.19 +        List<Long> highlightSpans = Pojson.load(ArrayList.class, highlightSpec);
    2.20 +        Map<String, Object> configurationData = new HashMap<String, Object>();
    2.21 +        String[] highlights = colorTokens(content, highlightSpans);
    2.22 +
    2.23 +        configurationData.put("spans", highlights[0]);
    2.24 +        configurationData.put("categories", highlights[1]);
    2.25 +        configurationData.put("code", translate(content));
    2.26 +
    2.27 +        return FreemarkerUtilities.processTemplate("org/netbeans/modules/jackpot30/backend/ui/showCode.html", configurationData);
    2.28 +    }
    2.29 +
    2.30 +    static String[] colorTokens(String content, List<Long> highlight) {
    2.31          TokenSequence<?> ts = TokenHierarchy.create(content, JavaTokenId.language()).tokenSequence();
    2.32          StringBuilder spans = new StringBuilder();
    2.33          StringBuilder cats  = new StringBuilder();
    2.34 -        int currentOffset = 0;
    2.35 +        long currentOffset = 0;
    2.36 +        boolean cont = false;
    2.37  
    2.38 -        while (ts.moveNext()) {
    2.39 +        while (cont || ts.moveNext()) {
    2.40              if (spans.length() > 0) spans.append(", ");
    2.41 -            int endOffset = ts.offset() + ts.token().length();
    2.42 +
    2.43 +            long endOffset = ts.offset() + ts.token().length();
    2.44 +            boolean foundHighlight = false;
    2.45 +
    2.46 +            cont = false;
    2.47 +            
    2.48 +            for (int i = 0; i < highlight.size(); i += 2) {
    2.49 +                if (   currentOffset <= highlight.get(i)
    2.50 +                    && endOffset >= highlight.get(i)) {
    2.51 +                    if (currentOffset < highlight.get(i)) {
    2.52 +                        endOffset = highlight.get(i);
    2.53 +                        cont = true;
    2.54 +                    } else  if ((highlight.get(i + 1) + 1) < endOffset) {
    2.55 +                        endOffset = highlight.get(i + 1) + 1;
    2.56 +                        cont = true;
    2.57 +                        foundHighlight = true;
    2.58 +                    } else {
    2.59 +                        foundHighlight = true;
    2.60 +                    }
    2.61 +                } else if (   highlight.get(i) <= currentOffset
    2.62 +                           && (highlight.get(i + 1) + 1) > endOffset) {
    2.63 +                    foundHighlight = true;
    2.64 +                } else if (   currentOffset < (highlight.get(i + 1) + 1)
    2.65 +                           && (highlight.get(i + 1) + 1) < endOffset) {
    2.66 +                    endOffset = highlight.get(i + 1) + 1;
    2.67 +                    cont = true;
    2.68 +                    foundHighlight = true;
    2.69 +                }
    2.70 +            }
    2.71 +
    2.72              spans.append(endOffset - currentOffset);
    2.73 -            currentOffset = endOffset;
    2.74              String category = ts.token().id().primaryCategory();
    2.75  
    2.76 +            char cat;
    2.77 +
    2.78              if ("keyword".equals(category)) {
    2.79 -                cats.append("K");
    2.80 +                cat = 'K';
    2.81              } else if ("keyword-directive".equals(category)) {
    2.82 -                cats.append("K");
    2.83 +                cat = 'K';
    2.84              } else if ("literal".equals(category)) {
    2.85 -                cats.append("K");
    2.86 +                cat = 'K';
    2.87              } else if ("whitespace".equals(category)) {
    2.88 -                cats.append("W");
    2.89 +                cat = 'W';
    2.90              } else if ("comment".equals(category)) {
    2.91 -                cats.append("C");
    2.92 +                cat = 'C';
    2.93              } else if ("character".equals(category)) {
    2.94 -                cats.append("H");
    2.95 +                cat = 'H';
    2.96              } else if ("number".equals(category)) {
    2.97 -                cats.append("N");
    2.98 +                cat = 'N';
    2.99              } else if ("string".equals(category)) {
   2.100 -                cats.append("S");
   2.101 +                cat = 'S';
   2.102              } else {
   2.103 -                cats.append("E");
   2.104 +                cat = 'E';
   2.105              }
   2.106 +
   2.107 +            if (foundHighlight) cat++;
   2.108 +
   2.109 +            cats.append(cat);
   2.110 +
   2.111 +            currentOffset = endOffset;
   2.112          }
   2.113  
   2.114 -        Map<String, Object> configurationData = new HashMap<String, Object>();
   2.115 -
   2.116 -        configurationData.put("spans", spans.toString());
   2.117 -        configurationData.put("categories", cats.toString());
   2.118 -        configurationData.put("code", translate(content));
   2.119 -
   2.120 -        return FreemarkerUtilities.processTemplate("org/netbeans/modules/jackpot30/backend/ui/showCode.html", configurationData);
   2.121 +        return new String[] {
   2.122 +            spans.toString(),
   2.123 +            cats.toString()
   2.124 +        };
   2.125      }
   2.126  
   2.127      //XXX: usages on fields do not work because the field signature in the index contain also the field type
     3.1 --- a/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/showCode.html	Fri Jul 13 11:06:24 2012 +0200
     3.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/showCode.html	Mon Jul 16 16:16:38 2012 +0200
     3.3 @@ -25,6 +25,15 @@
     3.4          .H {color: #006F00;}
     3.5          .N {color: #780000;}
     3.6          .S {color: #99009D;}
     3.7 +        .E {}
     3.8 +        .W {}
     3.9 +        .L {color: #0000FF; font-weight: bold;background-color:#DDDD00;}
    3.10 +        .D {color: #737373;background-color:#DDDD00;}
    3.11 +        .I {color: #006F00;background-color:#DDDD00;}
    3.12 +        .O {color: #780000;background-color:#DDDD00;}
    3.13 +        .T {color: #99009D;background-color:#DDDD00;}
    3.14 +        .F {background-color:#DDDD00;}
    3.15 +        .X {background-color:#DDDD00;}
    3.16      </style>
    3.17  </head>
    3.18  <body>
     4.1 --- a/remoting/server/web/web.ui/test/org/netbeans/modules/jackpot30/backend/ui/UITest.java	Fri Jul 13 11:06:24 2012 +0200
     4.2 +++ b/remoting/server/web/web.ui/test/org/netbeans/modules/jackpot30/backend/ui/UITest.java	Mon Jul 16 16:16:38 2012 +0200
     4.3 @@ -42,6 +42,8 @@
     4.4  
     4.5  package org.netbeans.modules.jackpot30.backend.ui;
     4.6  
     4.7 +import java.util.ArrayList;
     4.8 +import java.util.Arrays;
     4.9  import junit.framework.TestCase;
    4.10  
    4.11  /**
    4.12 @@ -71,4 +73,22 @@
    4.13          assertEquals("METHOD:org.netbeans.modules.java.hints.spiimpl.batch.BatchUtilities:fixDependencies:(Lorg/openide/filesystems/FileObject;Ljava/util/List;Ljava/util/Map;)Z",
    4.14                       UI.simplify("METHOD:org.netbeans.modules.java.hints.spiimpl.batch.BatchUtilities:fixDependencies:(Lorg/openide/filesystems/FileObject;Ljava/util/List<Lorg/netbeans/spi/java/hints/JavaFix;>;Ljava/util/Map<Lorg/netbeans/api/project/Project;Ljava/util/Set<Ljava/lang/String;>;>;)Z;"));
    4.15      }
    4.16 +
    4.17 +    public void testSpansColoring() {
    4.18 +        String[] coloring = UI.colorTokens("package test; public class Test { }", new ArrayList<Long>());
    4.19 +        assertEquals("7, 1, 4, 1, 1, 6, 1, 5, 1, 4, 1, 1, 1, 1", coloring[0]);
    4.20 +        assertEquals("KWEEWKWKWEWEWE", coloring[1]);
    4.21 +        coloring = UI.colorTokens("package test; public class Test { }", Arrays.asList(0L, 6L));
    4.22 +        assertEquals("7, 1, 4, 1, 1, 6, 1, 5, 1, 4, 1, 1, 1, 1", coloring[0]);
    4.23 +        assertEquals("LWEEWKWKWEWEWE", coloring[1]);
    4.24 +        coloring = UI.colorTokens("package test; public class Test { }", Arrays.asList(1L, 3L));
    4.25 +        assertEquals("1, 3, 3, 1, 4, 1, 1, 6, 1, 5, 1, 4, 1, 1, 1, 1", coloring[0]);
    4.26 +        assertEquals("KLKWEEWKWKWEWEWE", coloring[1]);
    4.27 +        coloring = UI.colorTokens("package test; public class Test { }", Arrays.asList(16L, 17L));
    4.28 +        assertEquals("7, 1, 4, 1, 1, 2, 2, 2, 1, 5, 1, 4, 1, 1, 1, 1", coloring[0]);
    4.29 +        assertEquals("KWEEWKLKWKWEWEWE", coloring[1]);
    4.30 +        coloring = UI.colorTokens("package test; public class Test { }", Arrays.asList(3L, 17L));
    4.31 +        assertEquals("3, 4, 1, 4, 1, 1, 4, 2, 1, 5, 1, 4, 1, 1, 1, 1", coloring[0]);
    4.32 +        assertEquals("KLXFFXLKWKWEWEWE", coloring[1]);
    4.33 +    }
    4.34  }