aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-colorizer/src
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2010-09-06 14:08:06 +0000
committersimonbrandhof <simon.brandhof@gmail.com>2010-09-06 14:08:06 +0000
commitaeadc1f9129274949daaa57738c7c4550bdfbc7b (patch)
tree08dadf5ef7474fc41d1d48f74648f1ba8b55f34d /sonar-colorizer/src
downloadsonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.tar.gz
sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.zip
SONAR-236 remove deprecated code from checkstyle plugin + display default value of rule parameters in Q profile console
Diffstat (limited to 'sonar-colorizer/src')
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/CDocTokenizer.java28
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizer.java41
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/CodeColorizer.java71
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/CppDocTokenizer.java31
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyKeywords.java45
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyTokenizers.java37
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlCodeBuilder.java104
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlDecorator.java124
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlOptions.java120
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlRenderer.java64
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/InlineDocTokenizer.java56
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/JavaAnnotationTokenizer.java54
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/JavaConstantTokenizer.java80
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/JavaKeywords.java48
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/JavaTokenizers.java37
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/JavadocTokenizer.java31
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/KeywordsTokenizer.java95
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/LiteralTokenizer.java81
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/MultilinesDocTokenizer.java117
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/NotThreadSafeTokenizer.java30
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/RegexpTokenizer.java63
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/Renderer.java31
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/StringTokenizer.java40
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/SynhtaxHighlightingException.java36
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/Tokenizer.java31
-rw-r--r--sonar-colorizer/src/main/java/org/sonar/colorizer/TokenizerDispatcher.java65
-rw-r--r--sonar-colorizer/src/main/resources/sonar-colorizer.css61
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/CDocTokenizerTest.java49
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizerTest.java46
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/CodeColorizerTest.java129
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/CppTokenizerTest.java59
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlCodeBuilderTest.java81
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlDecoratorTest.java94
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlRendererTest.java71
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/JavaAnnotationTokenizerTest.java42
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/JavaConstantTokenizerTest.java72
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/JavaKeywordsTest.java36
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/JavaTokenizersTest.java56
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/JavadocTokenizerTest.java42
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/KeywordsTokenizerTest.java58
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/LiteralTokenizerTest.java59
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/MultilinesDocTokenizerTest.java80
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/RegexpTokenizerTest.java28
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/SyntaxHighlighterTestingHarness.java11
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/TokenizerDispatcherTest.java81
-rw-r--r--sonar-colorizer/src/test/java/org/sonar/colorizer/UserGuideTest.java76
-rw-r--r--sonar-colorizer/src/test/resources/org/sonar/colorizer/HtmlRendererTest/Sample.java17
-rw-r--r--sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.groovy13
-rw-r--r--sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.java52
-rw-r--r--sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/SingleLine.java1
50 files changed, 2874 insertions, 0 deletions
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/CDocTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/CDocTokenizer.java
new file mode 100644
index 00000000000..ce146f9ec74
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/CDocTokenizer.java
@@ -0,0 +1,28 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+public class CDocTokenizer extends InlineDocTokenizer {
+
+ public CDocTokenizer(String tagBefore, String tagAfter) {
+ super("//", tagBefore, tagAfter);
+ }
+
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizer.java
new file mode 100644
index 00000000000..e54470b977d
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizer.java
@@ -0,0 +1,41 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Set;
+
+public class CaseInsensitiveKeywordsTokenizer extends KeywordsTokenizer {
+
+ public CaseInsensitiveKeywordsTokenizer(String tagBefore, String tagAfter, Set<String> keywords) {
+ super(tagBefore, tagAfter, keywords);
+ setCaseInsensitive(true);
+ }
+
+ public CaseInsensitiveKeywordsTokenizer(String tagBefore, String tagAfter, String... keywords) {
+ super(tagBefore, tagAfter, keywords);
+ setCaseInsensitive(true);
+ }
+
+ public KeywordsTokenizer clone() {
+ KeywordsTokenizer clone = (KeywordsTokenizer) super.clone();
+ clone.setCaseInsensitive(true);
+ return clone;
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/CodeColorizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/CodeColorizer.java
new file mode 100644
index 00000000000..a348fa81cff
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/CodeColorizer.java
@@ -0,0 +1,71 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.io.Reader;
+import java.util.List;
+
+public class CodeColorizer {
+
+ private List<Tokenizer> tokenizers = null;
+
+ public CodeColorizer(List<Tokenizer> tokenizers) {
+ this.tokenizers = tokenizers;
+ }
+
+ public CodeColorizer(Format format) {
+ this.tokenizers = format.getTokenizers();
+ }
+
+ public String toHtml(Reader code) {
+ return toHtml(code, null);
+ }
+
+ public String toHtml(Reader code, HtmlOptions options) {
+ HtmlOptions opts = (options == null ? HtmlOptions.DEFAULT : options);
+ return new HtmlRenderer(opts).render(code, tokenizers);
+ }
+
+ public static String javaToHtml(Reader code, HtmlOptions options) {
+ return new CodeColorizer(Format.JAVA).toHtml(code, options);
+ }
+
+ public static String groovyToHtml(Reader code, HtmlOptions options) {
+ return new CodeColorizer(Format.GROOVY).toHtml(code, options);
+ }
+
+ public static String getCss() {
+ return HtmlDecorator.getCss();
+ }
+
+ public enum Format {
+ JAVA(JavaTokenizers.forHtml()), GROOVY(GroovyTokenizers.forHtml());
+
+ private List<Tokenizer> tokenizers;
+
+ Format(List<Tokenizer> tokenizers) {
+ this.tokenizers = tokenizers;
+ }
+
+ public List<Tokenizer> getTokenizers() {
+ return tokenizers;
+ }
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/CppDocTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/CppDocTokenizer.java
new file mode 100644
index 00000000000..d965b6c652f
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/CppDocTokenizer.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+public class CppDocTokenizer extends MultilinesDocTokenizer {
+
+ public CppDocTokenizer(String tagBefore, String tagAfter) {
+ super("/*", "*/", tagBefore, tagAfter);
+ }
+
+ public CppDocTokenizer() {
+ this("", "");
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyKeywords.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyKeywords.java
new file mode 100644
index 00000000000..bc97ba94267
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyKeywords.java
@@ -0,0 +1,45 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class GroovyKeywords {
+
+ private static final Set<String> KEYWORDS = new HashSet<String>();
+
+ private static final String[] GROOVY_KEYWORDS = new String[] { "as", "assert", "break", "case", "catch", "class", "continue", "def",
+ "default", "do"
+ , "else", "extends", "finally", "for", "if", "in", "implements", "import", "instanceof", "interface", "new", "package",
+ "property", "return", "switch", "throw", "throws", "try", "while" };
+
+ static {
+ Collections.addAll(KEYWORDS, GROOVY_KEYWORDS);
+ }
+
+ private GroovyKeywords() {
+ }
+
+ public static Set<String> get() {
+ return Collections.unmodifiableSet(KEYWORDS);
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyTokenizers.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyTokenizers.java
new file mode 100644
index 00000000000..4e86ed7eec0
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/GroovyTokenizers.java
@@ -0,0 +1,37 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public final class GroovyTokenizers {
+
+ private GroovyTokenizers() {
+ }
+
+ public static List<Tokenizer> forHtml() {
+ return Collections.unmodifiableList(Arrays.asList(new JavaAnnotationTokenizer("<span class=\"a\">", "</span>"), new LiteralTokenizer(
+ "<span class=\"s\">", "</span>"), new CDocTokenizer("<span class=\"cd\">", "</span>"), new CppDocTokenizer("<span class=\"cppd\">",
+ "</span>"), new JavadocTokenizer("<span class=\"j\">", "</span>"), new JavaConstantTokenizer("<span class=\"c\">", "</span>"),
+ new KeywordsTokenizer("<span class=\"k\">", "</span>", GroovyKeywords.get())));
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlCodeBuilder.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlCodeBuilder.java
new file mode 100644
index 00000000000..ea530abc037
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlCodeBuilder.java
@@ -0,0 +1,104 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class HtmlCodeBuilder implements Appendable {
+
+ private StringBuilder colorizedCode = new StringBuilder();
+ private Map variables = new HashMap(); // stateful data
+
+ public Appendable append(CharSequence csq) {
+ for (int i = 0; i < csq.length(); i++) {
+ append(csq.charAt(i));
+ }
+ return this;
+ }
+
+ public Appendable append(char c) {
+ if (c == '<') {
+ colorizedCode.append("&lt;");
+ } else if (c == '>') {
+ colorizedCode.append("&gt;");
+ } else {
+ colorizedCode.append(c);
+ }
+ return this;
+ }
+
+ public Appendable append(CharSequence csq, int start, int end) {
+ for (int i = start; i < end; i++) {
+ append(csq.charAt(i));
+ }
+ return this;
+ }
+
+ public void appendWithoutTransforming(String htmlTag) {
+ colorizedCode.append(htmlTag);
+ }
+
+ public String toString() {
+ return colorizedCode.toString();
+ }
+
+ public StringBuilder getColorizedCode() {
+ return colorizedCode;
+ }
+
+ /**
+ * Save a stateful variable.
+ *
+ * @param key
+ * can NOT be null
+ * @param value
+ * can be null
+ */
+ public void setVariable(Object key, Object value) {
+ variables.put(key, value);
+ }
+
+ /**
+ * Get a stateful variable. Return null if not found.
+ */
+ public Object getVariable(Object key) {
+ return variables.get(key);
+ }
+
+ /**
+ * Get a stateful variable. Return the default value if not found.
+ */
+ public Object getVariable(Object key, Object defaultValue) {
+ Object result = variables.get(key);
+ if (result == null) {
+ result = defaultValue;
+ }
+ return result;
+ }
+
+ /**
+ * All stateful variables
+ */
+ public Map getVariables() {
+ return variables;
+ }
+
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlDecorator.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlDecorator.java
new file mode 100644
index 00000000000..2d65143c106
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlDecorator.java
@@ -0,0 +1,124 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.sonar.channel.CodeReader;
+
+public class HtmlDecorator extends Tokenizer {
+
+ private static final String CSS_PATH = "/sonar-colorizer.css";
+
+ private HtmlOptions options;
+ private int lineId = 1;
+ private boolean checked = false;
+ private boolean beginOfLine = true;
+ private boolean endOfLine = false;
+
+ public HtmlDecorator(HtmlOptions options) {
+ this.options = options;
+ this.lineId = options.getFirstLineId();
+ }
+
+ public String getTagBeginOfFile() {
+ StringBuilder sb = new StringBuilder();
+ if (options.isGenerateHtmlHeader()) {
+ sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
+ + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html><head><style type=\"text/css\">");
+ sb.append(getCss());
+ sb.append("</style></head><body>");
+ }
+ sb.append("<table class=\"code\" id=\"");
+ if (options.getTableId() != null) {
+ sb.append(options.getTableId());
+ }
+ sb.append("\"><tbody>");
+ return sb.toString();
+ }
+
+ public String getTagEndOfFile() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("</pre></td></tr></tbody></table>");
+ if (options.isGenerateHtmlHeader()) {
+ sb.append("</body></html>");
+ }
+ return sb.toString();
+ }
+
+ public String getTagBefore() {
+ StringBuilder sb = new StringBuilder();
+ if (beginOfLine) {
+ sb.append("<tr id=\"");
+ sb.append(lineId++);
+ sb.append("\"><td><pre>");
+ }
+ return sb.toString();
+ }
+
+ public String getTagAfter() {
+ if (endOfLine) {
+ return "</pre></td></tr>";
+ }
+ return "";
+ }
+
+ private boolean hasNextToken(CodeReader code) {
+ if (checked) {
+ checked = false;
+ return false;
+ }
+ int lastChar = code.lastChar();
+ beginOfLine = (lastChar == -1 || lastChar == (int) '\n');
+
+ int peek = code.peek();
+ endOfLine = (peek == (int) '\n' || peek == -1);
+
+ checked = beginOfLine || endOfLine;
+ return checked;
+ }
+
+ @Override
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (hasNextToken(code)) {
+ codeBuilder.appendWithoutTransforming(getTagBefore());
+ codeBuilder.appendWithoutTransforming(getTagAfter());
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static String getCss() {
+ InputStream input = null;
+ try {
+ input = HtmlRenderer.class.getResourceAsStream(CSS_PATH);
+ return IOUtils.toString(input);
+
+ } catch (IOException e) {
+ throw new SynhtaxHighlightingException("Sonar Colorizer CSS file not found: " + CSS_PATH, e);
+
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlOptions.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlOptions.java
new file mode 100644
index 00000000000..f26a710e80b
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlOptions.java
@@ -0,0 +1,120 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+public class HtmlOptions {
+ public static final HtmlOptions DEFAULT = new HtmlOptions(true, null, true);
+ public static final OnlySyntaxHtmlOptions ONLY_SYNTAX = new OnlySyntaxHtmlOptions();
+
+ private boolean generateTable = true;
+ private boolean generateHtmlHeader = true;
+ private String tableId = null;
+ private int firstLineId = 1;
+
+ public HtmlOptions() {
+ }
+
+ public HtmlOptions(boolean generateTable, String tableId, boolean generateHtmlHeader) {
+ this.generateTable = generateTable;
+ this.generateHtmlHeader = generateHtmlHeader;
+ this.tableId = tableId;
+ }
+
+ public boolean isGenerateTable() {
+ return generateTable;
+ }
+
+ public HtmlOptions setGenerateTable(boolean b) {
+ this.generateTable = b;
+ return this;
+ }
+
+ /**
+ * Used only if isGenerateTable() is true
+ */
+ public boolean isGenerateHtmlHeader() {
+ return generateHtmlHeader;
+ }
+
+ /**
+ * Defines if the HTML header, including CSS, must be generated.
+ */
+ public HtmlOptions setGenerateHtmlHeader(boolean b) {
+ this.generateHtmlHeader = b;
+ return this;
+ }
+
+ public String getTableId() {
+ return tableId;
+ }
+
+ /**
+ * Used only if isGenerateTable() is true. This field is optional.
+ */
+ public HtmlOptions setTableId(String id) {
+ this.tableId = id;
+ return this;
+ }
+
+ /**
+ * Used only if isGenerateTable() is true. Default value is 1.
+ */
+ public int getFirstLineId() {
+ return firstLineId;
+ }
+
+ public HtmlOptions setFirstLineId(int i) {
+ this.firstLineId = i;
+ return this;
+ }
+}
+
+class OnlySyntaxHtmlOptions extends HtmlOptions {
+
+ @Override
+ public boolean isGenerateTable() {
+ return false;
+ }
+
+ @Override
+ public boolean isGenerateHtmlHeader() {
+ return false;
+ }
+
+ @Override
+ public String getTableId() {
+ return null;
+ }
+
+ @Override
+ public HtmlOptions setGenerateHtmlHeader(boolean b) {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public HtmlOptions setGenerateTable(boolean b) {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public HtmlOptions setTableId(String id) {
+ throw new IllegalStateException();
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlRenderer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlRenderer.java
new file mode 100644
index 00000000000..5f11b867584
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/HtmlRenderer.java
@@ -0,0 +1,64 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.sonar.channel.Channel;
+import org.sonar.channel.CodeReader;
+
+public class HtmlRenderer extends Renderer {
+
+ private HtmlOptions options = null;
+
+ public HtmlRenderer(HtmlOptions options) {
+ this.options = options;
+ }
+
+ public HtmlRenderer() {
+ this(HtmlOptions.DEFAULT);
+ }
+
+ public String render(Reader code, List<? extends Channel<HtmlCodeBuilder>> tokenizers) {
+ try {
+ List<Channel<HtmlCodeBuilder>> allTokenizers = new ArrayList<Channel<HtmlCodeBuilder>>();
+ HtmlCodeBuilder codeBuilder = new HtmlCodeBuilder();
+ HtmlDecorator htmlDecorator = new HtmlDecorator(options);
+
+ // optimization
+ if (options != null && options.isGenerateTable()) {
+ codeBuilder.appendWithoutTransforming(htmlDecorator.getTagBeginOfFile());
+ allTokenizers.add(htmlDecorator);
+ }
+ allTokenizers.addAll(tokenizers);
+
+ new TokenizerDispatcher(allTokenizers).colorize(new CodeReader(code), codeBuilder);
+ // optimization
+ if (options != null && options.isGenerateTable()) {
+ codeBuilder.appendWithoutTransforming(htmlDecorator.getTagEndOfFile());
+ }
+ return codeBuilder.toString();
+ } catch (Exception e) {
+ throw new SynhtaxHighlightingException("Can not render code", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/InlineDocTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/InlineDocTokenizer.java
new file mode 100644
index 00000000000..ad12bf829c3
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/InlineDocTokenizer.java
@@ -0,0 +1,56 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Arrays;
+
+import org.sonar.channel.CodeReader;
+import org.sonar.channel.EndMatcher;
+
+public abstract class InlineDocTokenizer extends Tokenizer {
+
+ private final String tagBefore;
+ private final String tagAfter;
+
+ private final char[] startToken;
+
+ public InlineDocTokenizer(String startToken, String tagBefore, String tagAfter) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ this.startToken = startToken.toCharArray();
+ }
+
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (code.peek() == startToken[0] && Arrays.equals(code.peek(startToken.length), startToken)) {
+ codeBuilder.appendWithoutTransforming(tagBefore);
+ code.popTo(new EndMatcher() {
+
+ public boolean match(int endFlag) {
+ return endFlag == '\r' || endFlag == '\n';
+ }
+ }, codeBuilder);
+ codeBuilder.appendWithoutTransforming(tagAfter);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaAnnotationTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaAnnotationTokenizer.java
new file mode 100644
index 00000000000..346855eed46
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaAnnotationTokenizer.java
@@ -0,0 +1,54 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.sonar.channel.CodeReader;
+import org.sonar.channel.EndMatcher;
+
+public class JavaAnnotationTokenizer extends Tokenizer {
+
+ private final String tagBefore;
+ private final String tagAfter;
+
+ public JavaAnnotationTokenizer(String tagBefore, String tagAfter) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ }
+
+ private static final EndMatcher endTokenMatcher = new EndMatcher() {
+
+ public boolean match(int endFlag) {
+ return !Character.isJavaIdentifierPart(endFlag);
+ }
+ };
+
+ @Override
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (code.peek() == '@') {
+ codeBuilder.appendWithoutTransforming(tagBefore);
+ code.popTo(endTokenMatcher, codeBuilder);
+ codeBuilder.appendWithoutTransforming(tagAfter);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaConstantTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaConstantTokenizer.java
new file mode 100644
index 00000000000..17fd02cf151
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaConstantTokenizer.java
@@ -0,0 +1,80 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.sonar.channel.CodeReader;
+import org.sonar.channel.EndMatcher;
+
+/**
+ * Detect Java constant
+ */
+public class JavaConstantTokenizer extends Tokenizer {
+
+ private final String tagBefore;
+ private final String tagAfter;
+ private final static int DOT = '.';
+
+ public JavaConstantTokenizer(String tagBefore, String tagAfter) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ }
+
+ private boolean hasNextToken(CodeReader code) {
+ int lastChar = code.lastChar();
+ if (isJavaConstantStart(code.peek()) && !Character.isJavaIdentifierPart(lastChar) && !Character.isJavaIdentifierStart(lastChar)
+ && lastChar != DOT) {
+ String constant = code.peekTo(endTokenMatcher);
+ int nextCharAfterConstant = code.peek(constant.length() + 1)[constant.length()];
+ if (nextCharAfterConstant != 0 && Character.isJavaIdentifierPart(nextCharAfterConstant)) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (hasNextToken(code)) {
+ codeBuilder.appendWithoutTransforming(tagBefore);
+ code.popTo(endTokenMatcher, codeBuilder);
+ codeBuilder.appendWithoutTransforming(tagAfter);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean isJavaConstantStart(int character) {
+ return Character.isUpperCase(character);
+ }
+
+ private boolean isJavaConstantPart(int character) {
+ return Character.isUpperCase(character) || character == '_' || character == '-' || Character.isDigit(character);
+ }
+
+ private EndMatcher endTokenMatcher = new EndMatcher() {
+
+ public boolean match(int endFlag) {
+ return !isJavaConstantPart(endFlag);
+ }
+ };
+
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaKeywords.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaKeywords.java
new file mode 100644
index 00000000000..b3ce2bbfed1
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaKeywords.java
@@ -0,0 +1,48 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class JavaKeywords {
+
+ private static final Set<String> KEYWORDS = new HashSet<String>();
+
+ private static final String[] JAVA_KEYWORDS = new String[] { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char",
+ "class", "const", "continue", "default",
+ "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for",
+ "goto", "if", "implements", "import", "instanceof",
+ "int", "interface", "long", "native", "new", "null", "package", "private",
+ "protected", "public", "return", "short", "static", "strictfp",
+ "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while"};
+
+ static {
+ Collections.addAll(KEYWORDS, JAVA_KEYWORDS);
+ }
+
+ private JavaKeywords() {
+ }
+
+ public static Set<String> get() {
+ return Collections.unmodifiableSet(KEYWORDS);
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaTokenizers.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaTokenizers.java
new file mode 100644
index 00000000000..e5bc1b5af1c
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavaTokenizers.java
@@ -0,0 +1,37 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public final class JavaTokenizers {
+
+ private JavaTokenizers() {
+ }
+
+ public static List<Tokenizer> forHtml() {
+ return Collections.unmodifiableList(Arrays.asList(new JavaAnnotationTokenizer("<span class=\"a\">", "</span>"), new LiteralTokenizer(
+ "<span class=\"s\">", "</span>"), new CDocTokenizer("<span class=\"cd\">", "</span>"), new JavadocTokenizer("<span class=\"j\">",
+ "</span>"), new CppDocTokenizer("<span class=\"cppd\">", "</span>"), new JavaConstantTokenizer("<span class=\"c\">", "</span>"),
+ new KeywordsTokenizer("<span class=\"k\">", "</span>", JavaKeywords.get())));
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/JavadocTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavadocTokenizer.java
new file mode 100644
index 00000000000..ccf39096475
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/JavadocTokenizer.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+public class JavadocTokenizer extends MultilinesDocTokenizer {
+
+ public JavadocTokenizer(String tagBefore, String tagAfter) {
+ super("/**", "*/", tagBefore, tagAfter);
+ }
+
+ public JavadocTokenizer() {
+ this("", "");
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/KeywordsTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/KeywordsTokenizer.java
new file mode 100644
index 00000000000..9d4dd3239d7
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/KeywordsTokenizer.java
@@ -0,0 +1,95 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.sonar.channel.CodeReader;
+
+/**
+ * Detect case-sensitive keywords
+ */
+public class KeywordsTokenizer extends NotThreadSafeTokenizer {
+
+ private final String tagBefore;
+ private final String tagAfter;
+ private boolean caseInsensitive = false;
+ private Matcher matcher;
+ private final StringBuilder tmpBuilder = new StringBuilder();
+ private final static String defaultRegex = "[a-zA-Z_][a-zA-Z0-9_]*+";
+
+ private Set<String> keywords = new HashSet<String>();
+
+ public KeywordsTokenizer(String tagBefore, String tagAfter, Set<String> keywords) {
+ this(tagBefore, tagAfter, keywords, defaultRegex);
+ }
+
+ public KeywordsTokenizer(String tagBefore, String tagAfter, Set<String> keywords, String regex) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ this.keywords = keywords;
+ this.matcher = Pattern.compile(regex).matcher("");
+ }
+
+ public KeywordsTokenizer(String tagBefore, String tagAfter, String... keywords) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ Collections.addAll(this.keywords, keywords);
+ this.matcher = Pattern.compile(defaultRegex).matcher("");
+ }
+
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (code.popTo(matcher, tmpBuilder) > 0) {
+ if (isKeyword(tmpBuilder.toString())) {
+ codeBuilder.appendWithoutTransforming(tagBefore);
+ codeBuilder.append(tmpBuilder);
+ codeBuilder.appendWithoutTransforming(tagAfter);
+ } else {
+ codeBuilder.append(tmpBuilder);
+ }
+ tmpBuilder.delete(0, tmpBuilder.length());
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isKeyword(String word) {
+ if ( !caseInsensitive && keywords.contains(word)) {
+ return true;
+ } else if (caseInsensitive && keywords.contains(word.toUpperCase())) {
+ return true;
+ }
+ return false;
+ }
+
+ public void setCaseInsensitive(boolean caseInsensitive) {
+ this.caseInsensitive = caseInsensitive;
+ }
+
+ public KeywordsTokenizer clone() {
+ KeywordsTokenizer clone = new KeywordsTokenizer(tagBefore, tagAfter, keywords, matcher.pattern().pattern());
+ clone.caseInsensitive = caseInsensitive;
+ return clone;
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/LiteralTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/LiteralTokenizer.java
new file mode 100644
index 00000000000..2c0c6c93468
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/LiteralTokenizer.java
@@ -0,0 +1,81 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.sonar.channel.CodeReader;
+import org.sonar.channel.EndMatcher;
+
+public class LiteralTokenizer extends Tokenizer {
+
+ private final String tagBefore;
+ private final String tagAfter;
+
+ public LiteralTokenizer(String tagBefore, String tagAfter) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ }
+
+ public LiteralTokenizer() {
+ this("", "");
+ }
+
+ @Override
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (code.peek() == '\'' || code.peek() == '\"') {
+ codeBuilder.appendWithoutTransforming(tagBefore);
+ int firstChar = code.peek();
+ code.popTo(new EndCommentMatcher(firstChar, code), codeBuilder);
+ codeBuilder.appendWithoutTransforming(tagAfter);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private static class EndCommentMatcher implements EndMatcher {
+
+ private final int firstChar;
+ private final CodeReader code;
+ private StringBuilder literalValue;
+
+ public EndCommentMatcher(int firstChar, CodeReader code) {
+ this.firstChar = firstChar;
+ this.code = code;
+ literalValue = new StringBuilder();
+ }
+
+ public boolean match(int endFlag) {
+ literalValue.append((char) endFlag);
+ return (code.lastChar() == firstChar && evenNumberOfBackSlashBeforeDelimiter() && literalValue.length() > 1);
+ }
+
+ private boolean evenNumberOfBackSlashBeforeDelimiter() {
+ int numberOfBackSlashChar = 0;
+ for (int index = literalValue.length() - 3; index >= 0; index--) {
+ if (literalValue.charAt(index) == '\\') {
+ numberOfBackSlashChar++;
+ } else {
+ break;
+ }
+ }
+ return numberOfBackSlashChar % 2 == 0;
+ }
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/MultilinesDocTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/MultilinesDocTokenizer.java
new file mode 100644
index 00000000000..8fb767d623f
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/MultilinesDocTokenizer.java
@@ -0,0 +1,117 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.Arrays;
+
+import org.sonar.channel.CodeReader;
+import org.sonar.channel.EndMatcher;
+
+public class MultilinesDocTokenizer extends Tokenizer {
+
+ private static final String COMMENT_STARTED_ON_PREVIOUS_LINE = "COMMENT_STARTED_ON_PREVIOUS_LINE";
+ private static final String COMMENT_TOKENIZER = "MULTILINE_COMMENT_TOKENIZER";
+ private final char[] startToken;
+ private final char[] endToken;
+ private final String tagBefore;
+ private final String tagAfter;
+
+ /**
+ * @deprecated endToken is hardcoded to star-slash, whatever the startToken !
+ */
+ @Deprecated
+ public MultilinesDocTokenizer(String startToken, String tagBefore, String tagAfter) {
+ this(startToken, "*/", tagBefore, tagAfter);
+ }
+
+ public MultilinesDocTokenizer(String startToken, String endToken, String tagBefore, String tagAfter) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ this.startToken = startToken.toCharArray();
+ this.endToken = endToken.toCharArray();
+ }
+
+ public boolean hasNextToken(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ return code.peek() != '\n'
+ && code.peek() != '\r'
+ && (isCommentStartedOnPreviousLine(codeBuilder) || (code.peek() == startToken[0] && Arrays.equals(code.peek(startToken.length),
+ startToken)));
+ }
+
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (hasNextToken(code, codeBuilder)) {
+ codeBuilder.appendWithoutTransforming(tagBefore);
+ code.popTo(new MultilineEndTokenMatcher(codeBuilder), codeBuilder);
+ codeBuilder.appendWithoutTransforming(tagAfter);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private class MultilineEndTokenMatcher implements EndMatcher {
+
+ private final HtmlCodeBuilder code;
+ private final StringBuilder colorizedCode;
+ private int commentSize = 0;
+
+ public MultilineEndTokenMatcher(HtmlCodeBuilder code) {
+ this.code = code;
+ this.colorizedCode = code.getColorizedCode();
+ }
+
+ public boolean match(int endFlag) {
+ commentSize++;
+ if (commentSize >= endToken.length + startToken.length || (commentSize >= endToken.length && isCommentStartedOnPreviousLine(code))) {
+ boolean matches = true;
+ for (int i = 1; i <= endToken.length; i++) {
+ if (colorizedCode.charAt(colorizedCode.length() - i) != endToken[endToken.length - i]) {
+ matches = false;
+ break;
+ }
+ }
+ if (matches) {
+ setCommentStartedOnPreviousLine(code, Boolean.FALSE);
+ return true;
+ }
+ }
+
+ if (endFlag == '\r' || endFlag == '\n') {
+ setCommentStartedOnPreviousLine(code, Boolean.TRUE);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private boolean isCommentStartedOnPreviousLine(HtmlCodeBuilder codeBuilder) {
+ Boolean b = (Boolean) codeBuilder.getVariable(COMMENT_STARTED_ON_PREVIOUS_LINE, Boolean.FALSE);
+ return (b == Boolean.TRUE) && (getTokenizerId().equals(codeBuilder.getVariable(COMMENT_TOKENIZER)));
+ }
+
+ private void setCommentStartedOnPreviousLine(HtmlCodeBuilder codeBuilder, Boolean b) {
+ codeBuilder.setVariable(COMMENT_STARTED_ON_PREVIOUS_LINE, b);
+ codeBuilder.setVariable(COMMENT_TOKENIZER, b ? getTokenizerId() : null);
+ }
+
+ private String getTokenizerId() {
+ return getClass().getSimpleName();
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/NotThreadSafeTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/NotThreadSafeTokenizer.java
new file mode 100644
index 00000000000..94eb919dcc7
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/NotThreadSafeTokenizer.java
@@ -0,0 +1,30 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+/**
+ * A thread safe Tokenizer. Before each use by the CodeColorizer, the method clone() is automatically
+ * called to clone the current instance.
+ *
+ */
+public abstract class NotThreadSafeTokenizer extends Tokenizer implements Cloneable {
+
+ public abstract NotThreadSafeTokenizer clone();
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/RegexpTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/RegexpTokenizer.java
new file mode 100644
index 00000000000..d0cb456e0c0
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/RegexpTokenizer.java
@@ -0,0 +1,63 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.sonar.channel.CodeReader;
+
+public class RegexpTokenizer extends NotThreadSafeTokenizer{
+
+ private final String tagBefore;
+ private final String tagAfter;
+ private final Matcher matcher;
+ private final StringBuilder tmpBuilder = new StringBuilder();
+
+ /**
+ * @param tagBefore
+ * Html tag to add before the token
+ * @param tagAfter
+ * Html tag to add after the token
+ * @param regexp
+ * Regular expression which must be used to match token
+ */
+ public RegexpTokenizer(String tagBefore, String tagAfter, String regexp) {
+ this.tagBefore = tagBefore;
+ this.tagAfter = tagAfter;
+ this.matcher = Pattern.compile(regexp).matcher("");
+ }
+
+ @Override
+ public boolean consume(CodeReader code, HtmlCodeBuilder codeBuilder) {
+ if (code.popTo(matcher, tmpBuilder) > 0) {
+ codeBuilder.appendWithoutTransforming(tagBefore);
+ codeBuilder.append(tmpBuilder);
+ codeBuilder.appendWithoutTransforming(tagAfter);
+ tmpBuilder.delete(0, tmpBuilder.length());
+ return true;
+ }
+ return false;
+ }
+
+ public RegexpTokenizer clone() {
+ return new RegexpTokenizer(tagBefore, tagAfter, matcher.pattern().pattern());
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/Renderer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/Renderer.java
new file mode 100644
index 00000000000..eaf572caecc
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/Renderer.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.io.Reader;
+import java.util.List;
+
+import org.sonar.channel.Channel;
+
+public abstract class Renderer {
+
+ public abstract String render(Reader code, List<? extends Channel<HtmlCodeBuilder>> tokenizers);
+
+} \ No newline at end of file
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/StringTokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/StringTokenizer.java
new file mode 100644
index 00000000000..7830575ea3f
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/StringTokenizer.java
@@ -0,0 +1,40 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.sonar.channel.CodeReader;
+
+public class StringTokenizer extends Tokenizer {
+
+ private final LiteralTokenizer tokenizer;
+
+ public StringTokenizer(String tagBefore, String tagAfter) {
+ tokenizer = new LiteralTokenizer(tagBefore, tagAfter);
+ }
+
+ public StringTokenizer() {
+ tokenizer = new LiteralTokenizer("", "");
+ }
+
+ @Override
+ public boolean consume(CodeReader code, HtmlCodeBuilder output) {
+ return tokenizer.consume(code, output);
+ }
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/SynhtaxHighlightingException.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/SynhtaxHighlightingException.java
new file mode 100644
index 00000000000..e7cdfa79639
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/SynhtaxHighlightingException.java
@@ -0,0 +1,36 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+public class SynhtaxHighlightingException extends RuntimeException {
+
+ public SynhtaxHighlightingException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ public SynhtaxHighlightingException(String arg0) {
+ super(arg0);
+ }
+
+ public SynhtaxHighlightingException(Throwable arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/Tokenizer.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/Tokenizer.java
new file mode 100644
index 00000000000..ee01df95b5b
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/Tokenizer.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.sonar.channel.Channel;
+
+/**
+ * A token highlighter is in charge to optionally consume the next characters (token) of a CodeReader
+ * and to add the highlighted token to an HtmlCodeBuilder.
+ *
+ * IMPORTANT: a Tokenizer must be THREAD-SAFE otherwise see NotThreadSafeTokenizer
+ */
+public abstract class Tokenizer extends Channel<HtmlCodeBuilder> {
+}
diff --git a/sonar-colorizer/src/main/java/org/sonar/colorizer/TokenizerDispatcher.java b/sonar-colorizer/src/main/java/org/sonar/colorizer/TokenizerDispatcher.java
new file mode 100644
index 00000000000..60c2b3be737
--- /dev/null
+++ b/sonar-colorizer/src/main/java/org/sonar/colorizer/TokenizerDispatcher.java
@@ -0,0 +1,65 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.List;
+
+import org.sonar.channel.Channel;
+import org.sonar.channel.CodeReader;
+
+public class TokenizerDispatcher {
+
+ private Channel[] tokenizers;
+
+ public TokenizerDispatcher(Channel<HtmlCodeBuilder>... tokenizers) {
+ this.tokenizers = tokenizers;
+ }
+
+ public TokenizerDispatcher(List<Channel<HtmlCodeBuilder>> tokenizers) {
+ this.tokenizers = tokenizers.toArray(new Channel[0]); // NOSONAR performance is not an issue here
+ }
+
+ public final String colorize(String code) {
+ HtmlCodeBuilder colorizedCode = new HtmlCodeBuilder();
+ colorize(new CodeReader(code), colorizedCode);
+ return colorizedCode.toString();
+ }
+
+ public final void colorize(CodeReader code, HtmlCodeBuilder colorizedCode) {
+ cloneNotThreadSafeTokenizers();
+ nextChar: while (code.peek() != -1) {
+ for (Channel<HtmlCodeBuilder> codeTokenizer : tokenizers) {
+ if (codeTokenizer.consume(code, colorizedCode)) {
+ continue nextChar;
+ }
+ }
+ colorizedCode.append((char) code.pop());
+ }
+ code.close();
+ }
+
+ private void cloneNotThreadSafeTokenizers() {
+ for (int i = 0; i < tokenizers.length; i++) {
+ if (tokenizers[i] instanceof NotThreadSafeTokenizer) {
+ tokenizers[i] = ((NotThreadSafeTokenizer) tokenizers[i]).clone();
+ }
+ }
+ }
+}
diff --git a/sonar-colorizer/src/main/resources/sonar-colorizer.css b/sonar-colorizer/src/main/resources/sonar-colorizer.css
new file mode 100644
index 00000000000..5e6807df539
--- /dev/null
+++ b/sonar-colorizer/src/main/resources/sonar-colorizer.css
@@ -0,0 +1,61 @@
+.code {
+ font-size: 12px;
+}
+
+.code pre {
+ font-family: Monospace;
+ margin: 0;
+ padding: 0 5px;
+ color: #111;
+ margin: 0;
+}
+
+/* for example java annotations */
+.code .a {
+ color: #808000;
+}
+
+/* constants */
+.code .c {
+ color: #660E80;
+ font-style: italic;
+ font-weight: bold;
+}
+
+/* javadoc */
+.code .j {
+ color: #666666;
+ font-style: normal;
+}
+
+/* classic comment */
+.code .cd {
+ color: #666666;
+ font-style: italic;
+}
+
+/* C++ doc */
+.code .cppd {
+ color: #666666;
+ font-style: italic;
+}
+
+/* keyword */
+.code .k {
+ color: #000080;
+ font-weight: bold;
+}
+
+/* string */
+.code .s {
+ color: #008000;
+ font-weight: bold;
+}
+
+/* keyword light*/
+.code .h {
+ color: #000080;
+ font-weight: normal;
+}
+
+
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/CDocTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/CDocTokenizerTest.java
new file mode 100644
index 00000000000..31b7e316de4
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/CDocTokenizerTest.java
@@ -0,0 +1,49 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.channel.CodeReader;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class CDocTokenizerTest {
+
+ private HtmlCodeBuilder codeBuilder;
+
+ @Before
+ public void init() {
+ codeBuilder = new HtmlCodeBuilder();
+ }
+
+ @Test
+ public void testRead() {
+ CDocTokenizer tokenizer = new CDocTokenizer("<c>", "</c>");
+ assertTrue(tokenizer.consume(new CodeReader("//this is a comment"), codeBuilder));
+ assertThat(codeBuilder.toString(), is("<c>//this is a comment</c>"));
+
+ assertFalse(tokenizer.consume(new CodeReader("this is not a comment"), codeBuilder));
+ assertThat(codeBuilder.toString(), is("<c>//this is a comment</c>"));
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizerTest.java
new file mode 100644
index 00000000000..8f6d7412b91
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/CaseInsensitiveKeywordsTokenizerTest.java
@@ -0,0 +1,46 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.sonar.colorizer.SyntaxHighlighterTestingHarness.highlight;
+
+import org.junit.Test;
+
+public class CaseInsensitiveKeywordsTokenizerTest {
+
+ @Test
+ public void hasNextToken() {
+ CaseInsensitiveKeywordsTokenizer tokenizer = new CaseInsensitiveKeywordsTokenizer("<k>", "</k>", "PROCEDURE");
+ assertThat(highlight("procedure name", tokenizer), is("<k>procedure</k> name"));
+ assertThat(highlight("Procedure name", tokenizer), is("<k>Procedure</k> name"));
+ assertThat(highlight("PROCEDURE name", tokenizer), is("<k>PROCEDURE</k> name"));
+ }
+
+ @Test
+ public void testClone() {
+ CaseInsensitiveKeywordsTokenizer tokenizer = new CaseInsensitiveKeywordsTokenizer("<k>", "</k>", "PROCEDURE");
+ Tokenizer cloneTokenizer = tokenizer.clone();
+ assertThat(tokenizer, is(not(cloneTokenizer)));
+ assertThat(highlight("procedure name", cloneTokenizer), is("<k>procedure</k> name"));
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/CodeColorizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/CodeColorizerTest.java
new file mode 100644
index 00000000000..0c5cd743f53
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/CodeColorizerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.number.OrderingComparisons.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Test;
+
+public class CodeColorizerTest {
+
+ @Test
+ public void javaToHtml() throws IOException {
+ Reader java = readFile("/org/sonar/colorizer/samples/Sample.java");
+
+ String html = CodeColorizer.javaToHtml(java, HtmlOptions.DEFAULT);
+
+ assertHtml(html);
+ assertContains(html, "<pre><span class=\"k\">public</span> <span class=\"k\">class</span> Sample {</pre>");
+ }
+
+ @Test
+ public void useHtmlOptions() throws IOException {
+ Reader java = readFile("/org/sonar/colorizer/samples/Sample.java");
+
+ HtmlOptions options = new HtmlOptions(true, "my-table-id", false);
+ String html = CodeColorizer.javaToHtml(java, options);
+
+ assertThat(html, containsString("<table class=\"code\" id=\"my-table-id\""));
+ assertThat(html, not(containsString("<style")));
+ }
+
+ @Test
+ public void groovyToHtml() throws IOException {
+ Reader groovy = readFile("/org/sonar/colorizer/samples/Sample.groovy");
+
+ String html = CodeColorizer.groovyToHtml(groovy, HtmlOptions.DEFAULT);
+
+ assertHtml(html);
+ assertContains(html, "<pre><span class=\"k\">class</span> Greet {</pre>");
+ }
+
+ @Test
+ public void getCss() {
+ assertThat(CodeColorizer.getCss().length(), greaterThan(100));
+ assertThat(CodeColorizer.getCss(), containsString(".code"));
+ }
+
+ @Test
+ public void mustBeThreadsafe() throws FileNotFoundException, InterruptedException, ExecutionException {
+ final int taskCount = 50;
+ final int threadCount = 5;
+
+ class ColorizerTask implements Callable<String> {
+
+ Reader java;
+
+ ColorizerTask() throws FileNotFoundException {
+ this.java = readFile("/org/sonar/colorizer/samples/Sample.java");
+ }
+
+ public String call() throws Exception {
+ return CodeColorizer.javaToHtml(java, HtmlOptions.ONLY_SYNTAX);
+ }
+ }
+
+ Collection<Callable<String>> tasks = new ArrayList<Callable<String>>();
+ for (int i = 0; i < taskCount; i++) {
+ tasks.add(new ColorizerTask());
+ }
+ List<Future<String>> futures = Executors.newFixedThreadPool(threadCount).invokeAll(tasks);
+
+ assertThat(futures.size(), is(taskCount));
+
+ // all html must be the same
+ String html = futures.get(0).get();
+ for (Future<String> future : futures) {
+ assertEquals(html, future.get());
+ }
+ }
+
+ private FileReader readFile(String path) throws FileNotFoundException {
+ return new FileReader(FileUtils.toFile(getClass().getResource(path)));
+ }
+
+ private void assertHtml(String html) {
+ assertContains(html, "<style", "<table class=\"code\"", "</html>");
+ }
+
+ private void assertContains(String html, String... strings) {
+ for (String string : strings) {
+ assertThat(html, containsString(string));
+ }
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/CppTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/CppTokenizerTest.java
new file mode 100644
index 00000000000..8547a69a2bc
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/CppTokenizerTest.java
@@ -0,0 +1,59 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.channel.CodeReader;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class CppTokenizerTest {
+
+ private HtmlCodeBuilder codeBuilder;
+
+ @Before
+ public void init() {
+ codeBuilder = new HtmlCodeBuilder();
+ }
+
+ @Test
+ public void testRead() {
+ CppDocTokenizer javadocTokenizer = new CppDocTokenizer("<c>", "</c>");
+ assertTrue(javadocTokenizer.consume(new CodeReader("/*this is a cpp comment*/ private"), codeBuilder));
+ assertEquals("<c>/*this is a cpp comment*/</c>", codeBuilder.toString());
+
+ assertFalse(javadocTokenizer.consume(new CodeReader("//this is not a cpp comment"), codeBuilder));
+ }
+
+
+ @Test
+ public void testReadOnMultilines() {
+ CppDocTokenizer javadocTokenizer = new CppDocTokenizer("<c>", "</c>");
+ CodeReader reader = new CodeReader("/*this is \n a cpp comment*/ private");
+ assertTrue(javadocTokenizer.consume(reader, codeBuilder));
+ assertEquals("<c>/*this is </c>", codeBuilder.toString());
+ codeBuilder.append((char)reader.pop());
+ assertTrue(javadocTokenizer.consume(reader, codeBuilder));
+ assertEquals("<c>/*this is </c>\n<c> a cpp comment*/</c>", codeBuilder.toString());
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlCodeBuilderTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlCodeBuilderTest.java
new file mode 100644
index 00000000000..5c64e5e6e62
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlCodeBuilderTest.java
@@ -0,0 +1,81 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+public class HtmlCodeBuilderTest {
+
+ private HtmlCodeBuilder builder;
+
+ @Before
+ public void init() {
+ builder = new HtmlCodeBuilder();
+ }
+
+ @Test
+ public void testAppendCharSequence() {
+ builder.append("freddy < olivier");
+ assertEquals("freddy &lt; olivier", builder.toString());
+ }
+
+ @Test
+ public void testAppendChar() {
+ builder.append('p');
+ builder.append('a');
+ builder.append('>');
+ assertEquals("pa&gt;", builder.toString());
+ }
+
+ @Test
+ public void testAppendCharSequenceIntInt() {
+ builder.append("freddy < olivier", 0, 2);
+ assertEquals("fr", builder.toString());
+ }
+
+ @Test
+ public void testAppendWithoutTransforming() {
+ builder.appendWithoutTransforming("<inside>outside");
+ assertEquals("<inside>outside", builder.toString());
+ }
+
+ @Test
+ public void testStatefulVariables() {
+ assertThat(builder.getVariable("foo"), nullValue());
+
+ builder.setVariable("foo", "xxx");
+ assertThat((String) builder.getVariable("foo"), is("xxx"));
+
+ builder.setVariable("foo", "yyy");
+ assertThat((String) builder.getVariable("foo"), is("yyy"));
+
+ builder.setVariable("foo", null);
+ assertThat((String) builder.getVariable("foo"), nullValue());
+
+ assertThat((String) builder.getVariable("foo", "default"), is("default"));
+ }
+
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlDecoratorTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlDecoratorTest.java
new file mode 100644
index 00000000000..6effeaa3698
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlDecoratorTest.java
@@ -0,0 +1,94 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.number.OrderingComparisons.greaterThan;
+import static org.junit.Assert.assertThat;
+import org.junit.Test;
+import static org.junit.internal.matchers.StringContains.containsString;
+
+public class HtmlDecoratorTest {
+
+ @Test
+ public void beginOfFileTag() {
+ HtmlDecorator decorator = new HtmlDecorator(HtmlOptions.DEFAULT);
+ String tag = decorator.getTagBeginOfFile();
+ assertContains(tag, "<html", "<style", "<table");
+ }
+
+ @Test
+ public void beginOfFileTagWithTableId() {
+ HtmlOptions options = new HtmlOptions().setGenerateTable(true).setTableId("foo");
+ HtmlDecorator decorator = new HtmlDecorator(options);
+
+ String tag = decorator.getTagBeginOfFile();
+
+ assertContains(tag, "<table class=\"code\" id=\"foo\">");
+ }
+
+ @Test
+ public void beginOfFileTagWithoutHeader() {
+ HtmlOptions options = new HtmlOptions().setGenerateTable(true).setGenerateHtmlHeader(false);
+ HtmlDecorator decorator = new HtmlDecorator(options);
+
+ String tag = decorator.getTagBeginOfFile();
+
+ assertNotContains(tag, "<html", "<style");
+ assertContains(tag, "<table");
+ }
+
+ @Test
+ public void endOfFileTag() {
+ HtmlDecorator decorator = new HtmlDecorator(HtmlOptions.DEFAULT);
+ String tag = decorator.getTagEndOfFile();
+ assertContains(tag, "</table>", "</body>", "</html>");
+ }
+
+ @Test
+ public void endOfFileTagWithoutHeader() {
+ HtmlOptions options = new HtmlOptions().setGenerateTable(true).setGenerateHtmlHeader(false);
+ HtmlDecorator decorator = new HtmlDecorator(options);
+
+ String tag = decorator.getTagEndOfFile();
+
+ assertContains(tag, "</table>");
+ assertNotContains(tag, "</body>", "</html>");
+ }
+
+ @Test
+ public void getCss() {
+ assertThat(HtmlDecorator.getCss().length(), greaterThan(100));
+ assertThat(HtmlDecorator.getCss(), containsString(".code"));
+ }
+
+
+ public void assertContains(String html, String... strings) {
+ for (String string : strings) {
+ assertThat(html, containsString(string));
+ }
+ }
+
+ public void assertNotContains(String html, String... strings) {
+ for (String string : strings) {
+ assertThat(html, not(containsString(string)));
+ }
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlRendererTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlRendererTest.java
new file mode 100644
index 00000000000..a3c5e9b8c77
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/HtmlRendererTest.java
@@ -0,0 +1,71 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Arrays;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Test;
+import org.sonar.channel.Channel;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.internal.matchers.StringContains.containsString;
+
+public class HtmlRendererTest {
+
+ private KeywordsTokenizer javaKeywordTokenizer = new KeywordsTokenizer("<span class='k'>", "</span>", JavaKeywords.get());
+
+ @Test
+ public void renderJavaSyntax() {
+ String html = new HtmlRenderer(HtmlOptions.ONLY_SYNTAX).render(new StringReader("public class Hello {"), Arrays
+ .<Channel<HtmlCodeBuilder>> asList(javaKeywordTokenizer));
+
+ assertThat(html, is("<span class='k'>public</span> <span class='k'>class</span> Hello {"));
+ }
+
+ @Test
+ public void supportHtmlSpecialCharacters() {
+ String html = new HtmlRenderer(HtmlOptions.ONLY_SYNTAX).render(new StringReader("foo(\"<html>\");"), Arrays
+ .<Channel<HtmlCodeBuilder>> asList(new LiteralTokenizer("<s>", "</s>")));
+
+ assertThat(html, is("foo(<s>\"&lt;html&gt;\"</s>);"));
+ }
+
+ @Test
+ public void renderJavaFile() throws IOException {
+ File java = FileUtils.toFile(getClass().getResource("/org/sonar/colorizer/HtmlRendererTest/Sample.java"));
+
+ String html = new HtmlRenderer().render(new FileReader(java), Arrays.<Channel<HtmlCodeBuilder>> asList(javaKeywordTokenizer));
+
+ assertThat(html, containsString("<html>"));
+ assertThat(html, containsString("<style"));
+ assertThat(html, containsString("<table class=\"code\""));
+ assertThat(html, containsString("public"));
+ assertThat(html, containsString("class"));
+ assertThat(html, containsString("Sample"));
+ assertThat(html, containsString("</html>"));
+ }
+
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaAnnotationTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaAnnotationTokenizerTest.java
new file mode 100644
index 00000000000..eb1fe8f0a0d
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaAnnotationTokenizerTest.java
@@ -0,0 +1,42 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.sonar.colorizer.SyntaxHighlighterTestingHarness.highlight;
+
+import org.junit.Test;
+
+public class JavaAnnotationTokenizerTest {
+
+ JavaAnnotationTokenizer tokenizer = new JavaAnnotationTokenizer("<a>", "</a>");
+
+ @Test
+ public void testHighlighting() {
+ assertThat(highlight("@deprecated public", tokenizer), is("<a>@deprecated</a> public"));
+ assertThat(highlight("import", tokenizer), is("import"));
+ }
+
+ @Test
+ public void testHighlightingWithProperties() {
+ assertThat(highlight("@Target(ElementType.METHOD)", tokenizer), is("<a>@Target</a>(ElementType.METHOD)"));
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaConstantTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaConstantTokenizerTest.java
new file mode 100644
index 00000000000..0c45b78734d
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaConstantTokenizerTest.java
@@ -0,0 +1,72 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.channel.CodeReader;
+
+public class JavaConstantTokenizerTest {
+
+ private JavaConstantTokenizer tokenizer;
+ private HtmlCodeBuilder codeBuilder;
+
+ @Before
+ public void init() {
+ tokenizer = new JavaConstantTokenizer("<c>", "</c>");
+ codeBuilder = new HtmlCodeBuilder();
+ }
+
+ @Test
+ public void testRead() {
+ assertTrue(tokenizer.consume(new CodeReader("CONSTANT"), codeBuilder));
+ assertTrue(tokenizer.consume(new CodeReader("IS_CONSTANT "), codeBuilder));
+ assertTrue(tokenizer.consume(new CodeReader("IS-CONSTANT "), codeBuilder));
+ assertFalse(tokenizer.consume(new CodeReader("Class"), codeBuilder));
+ assertFalse(tokenizer.consume(new CodeReader("_NOTACONSTANT"), codeBuilder));
+ assertFalse(tokenizer.consume(new CodeReader("IS_not_a_constant"), codeBuilder));
+ assertFalse(tokenizer.consume(new CodeReader("property"), codeBuilder));
+ assertFalse(tokenizer.consume(new CodeReader(" "), codeBuilder));
+ }
+
+ @Test
+ public void upperCaseWordsStartingWithADotShoutNotBeHighlighted() {
+ CodeReader reader = new CodeReader(".URL");
+ reader.pop();
+ assertFalse(tokenizer.consume(reader, codeBuilder));
+ }
+
+ @Test
+ public void hasNextTokenWhenFirstCharacterIsNotAConstant() {
+ CodeReader code = new CodeReader("sCONSTANT");
+ code.pop();
+ assertFalse(tokenizer.consume(code, codeBuilder));
+ }
+
+ @Test
+ public void nextToken() {
+ assertTrue(tokenizer.consume(new CodeReader("IS_TRUE = 4;"), codeBuilder));
+ assertEquals("<c>IS_TRUE</c>", codeBuilder.toString());
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaKeywordsTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaKeywordsTest.java
new file mode 100644
index 00000000000..2bd6e05484f
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaKeywordsTest.java
@@ -0,0 +1,36 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import org.junit.Test;
+import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
+
+public class JavaKeywordsTest {
+
+ @Test
+ public void get() {
+ assertThat(JavaKeywords.get().size(), is(53));
+ assertThat(JavaKeywords.get(), hasItem("true"));
+ assertThat(JavaKeywords.get(), hasItem("public"));
+ assertThat(JavaKeywords.get(), hasItem("switch"));
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaTokenizersTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaTokenizersTest.java
new file mode 100644
index 00000000000..dcf9e929627
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavaTokenizersTest.java
@@ -0,0 +1,56 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import static junit.framework.Assert.fail;
+
+import static org.hamcrest.number.OrderingComparisons.greaterThan;
+import static org.hamcrest.number.OrderingComparisons.lessThan;
+import static org.junit.Assert.assertThat;
+
+public class JavaTokenizersTest {
+
+ @Test
+ public void forHtml() {
+ assertThat(JavaTokenizers.forHtml().size(), greaterThan(3));
+ }
+
+ @Test
+ public void javadocIsDefinedBeforeCppComment() {
+ // just because /** must be detected before /*
+ assertThat(indexOf(JavaTokenizers.forHtml(), JavadocTokenizer.class),
+ lessThan(indexOf(JavaTokenizers.forHtml(), CppDocTokenizer.class)));
+ }
+
+ private Integer indexOf(List<Tokenizer> tokenizers, Class tokenizerClass) {
+ for (int i = 0; i < tokenizers.size(); i++) {
+ if (tokenizers.get(i).getClass().equals(tokenizerClass)) {
+ return i;
+ }
+ }
+
+ fail("Tokenizer not found: " + tokenizerClass);
+ return null;
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/JavadocTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavadocTokenizerTest.java
new file mode 100644
index 00000000000..08a560e0585
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/JavadocTokenizerTest.java
@@ -0,0 +1,42 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.sonar.colorizer.SyntaxHighlighterTestingHarness.highlight;
+
+import org.junit.Test;
+
+public class JavadocTokenizerTest {
+
+ JavadocTokenizer tokenizer = new JavadocTokenizer("<j>", "</j>");
+
+ @Test
+ public void testHighlighting() {
+ assertThat(highlight("/**this is a javadoc*/ public ...", tokenizer), is("<j>/**this is a javadoc*/</j> public ..."));
+ assertThat(highlight("//this is not a javadoc", tokenizer), is("//this is not a javadoc"));
+ }
+
+ @Test
+ public void testHighlightingOnMultipleLines() {
+ assertThat(highlight("/**this is \n a javadoc*/ private", tokenizer), is("<j>/**this is </j>\n<j> a javadoc*/</j> private"));
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/KeywordsTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/KeywordsTokenizerTest.java
new file mode 100644
index 00000000000..5a5968f59d8
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/KeywordsTokenizerTest.java
@@ -0,0 +1,58 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.sonar.colorizer.SyntaxHighlighterTestingHarness.highlight;
+
+import org.junit.Test;
+
+public class KeywordsTokenizerTest {
+
+ @Test
+ public void testColorizeKeywords() {
+ KeywordsTokenizer tokenizer = new KeywordsTokenizer("<s>", "</s>", "public", "new");
+ assertThat(highlight("new()", tokenizer), is("<s>new</s>()"));
+ assertThat(highlight("public new get()", tokenizer), is("<s>public</s> <s>new</s> get()"));
+ assertThat(highlight("publication", tokenizer), is("publication"));
+ }
+
+ @Test
+ public void testUnderscoreAndDigit() {
+ KeywordsTokenizer tokenizer = new KeywordsTokenizer("<s>", "</s>", "_01public");
+ assertThat(highlight("_01public", tokenizer), is("<s>_01public</s>"));
+ }
+
+ @Test
+ public void testCaseSensitive() {
+ KeywordsTokenizer tokenizer = new KeywordsTokenizer("<s>", "</s>", "public");
+ assertThat(highlight("PUBLIC Public public", tokenizer), is("PUBLIC Public <s>public</s>"));
+ }
+
+ @Test
+ public void testClone() {
+ KeywordsTokenizer tokenizer = new KeywordsTokenizer("<s>", "</s>", "public", "[a-z]+");
+ KeywordsTokenizer cloneTokenizer = tokenizer.clone();
+ assertThat(tokenizer, is(not(cloneTokenizer)));
+ assertThat(highlight("public 1234", cloneTokenizer), is("<s>public</s> 1234"));
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/LiteralTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/LiteralTokenizerTest.java
new file mode 100644
index 00000000000..cb975763cc2
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/LiteralTokenizerTest.java
@@ -0,0 +1,59 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.channel.CodeReader;
+
+public class LiteralTokenizerTest {
+
+ private HtmlCodeBuilder codeBuilder;
+
+ @Before
+ public void init() {
+ codeBuilder = new HtmlCodeBuilder();
+ }
+
+ @Test
+ public void nextToken() {
+ LiteralTokenizer tokenizer = new LiteralTokenizer("<s>", "</s>");
+ assertTrue(tokenizer.consume(new CodeReader("\"toto\";"), codeBuilder));
+ assertEquals("<s>\"toto\"</s>", codeBuilder.toString());
+ init();
+ assertTrue(tokenizer.consume(new CodeReader("\"\";"), codeBuilder));
+ assertEquals("<s>\"\"</s>", codeBuilder.toString());
+ init();
+ assertTrue(tokenizer.consume(new CodeReader("\'\';"), codeBuilder));
+ assertEquals("<s>\'\'</s>", codeBuilder.toString());
+ init();
+ assertTrue(tokenizer.consume(new CodeReader("\"(\\\"\").replace"), codeBuilder));
+ assertEquals("<s>\"(\\\"\"</s>", codeBuilder.toString());
+ init();
+ assertTrue(tokenizer.consume(new CodeReader("\'\\\\\';"), codeBuilder));
+ assertEquals("<s>\'\\\\\'</s>", codeBuilder.toString());
+ init();
+ assertTrue(tokenizer.consume(new CodeReader("\"to\\'to\""), codeBuilder));
+ assertEquals("<s>\"to\\'to\"</s>", codeBuilder.toString());
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/MultilinesDocTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/MultilinesDocTokenizerTest.java
new file mode 100644
index 00000000000..32a6f65d1d6
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/MultilinesDocTokenizerTest.java
@@ -0,0 +1,80 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+
+package org.sonar.colorizer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.channel.CodeReader;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class MultilinesDocTokenizerTest {
+
+ private HtmlCodeBuilder codeBuilder;
+
+ @Before
+ public void init() {
+ codeBuilder = new HtmlCodeBuilder();
+ }
+
+ @Test
+ public void testStandardComment() {
+ MultilinesDocTokenizer tokenizer = new MultiLineDocTokenizerImpl("{[||", "");
+ assertThat(tokenizer.hasNextToken(new CodeReader("{[|| And here is strange multi-line comment"), new HtmlCodeBuilder()), is(true));
+ assertThat(tokenizer.hasNextToken(new CodeReader("// this is not a strange multi-line comment"), new HtmlCodeBuilder()), is(false));
+ }
+
+ @Test
+ public void testLongStartToken() {
+ MultilinesDocTokenizer tokenizer = new MultiLineDocTokenizerImpl("/***", "**/");
+ assertTrue(tokenizer.consume(new CodeReader("/*** multi-line comment**/ private part"), codeBuilder));
+ assertEquals("/*** multi-line comment**/", codeBuilder.toString());
+ }
+
+ @Test
+ public void testStartTokenEndTokenOverlapping() {
+ MultilinesDocTokenizer tokenizer = new MultiLineDocTokenizerImpl("/*", "*/");
+ assertTrue(tokenizer.consume(new CodeReader("/*// multi-line comment*/ private part"), codeBuilder));
+ assertEquals("/*// multi-line comment*/", codeBuilder.toString());
+ }
+
+ @Test
+ public void testMultilinesComment() {
+ CodeReader reader = new CodeReader("/* multi-line comment\n*/ private part");
+ MultilinesDocTokenizer tokenizer = new MultiLineDocTokenizerImpl("/*", "*/");
+ assertTrue(tokenizer.consume(reader, codeBuilder));
+ assertEquals("/* multi-line comment", codeBuilder.toString());
+ reader.pop();
+ assertTrue(tokenizer.consume(reader, codeBuilder));
+ assertEquals("/* multi-line comment*/", codeBuilder.toString());
+ }
+
+ public class MultiLineDocTokenizerImpl extends MultilinesDocTokenizer {
+
+ public MultiLineDocTokenizerImpl(String startToken, String endToken) {
+ super(startToken, endToken, "", "");
+ }
+ }
+
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/RegexpTokenizerTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/RegexpTokenizerTest.java
new file mode 100644
index 00000000000..eb400e14a13
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/RegexpTokenizerTest.java
@@ -0,0 +1,28 @@
+package org.sonar.colorizer;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.sonar.colorizer.SyntaxHighlighterTestingHarness.highlight;
+
+import org.junit.Test;
+
+public class RegexpTokenizerTest {
+
+ RegexpTokenizer tokenHighlighter;;
+
+ @Test
+ public void testHighlight() {
+ tokenHighlighter = new RegexpTokenizer("<r>", "</r>", "[0-9]+");
+ assertThat(highlight("123, word = 435;", tokenHighlighter), is("<r>123</r>, word = <r>435</r>;"));
+ }
+
+ @Test
+ public void testClone() {
+ RegexpTokenizer tokenizer = new RegexpTokenizer("<r>", "</r>", "[a-z]+");
+ RegexpTokenizer cloneTokenizer = tokenizer.clone();
+ assertThat(tokenizer, is(not(cloneTokenizer)));
+ assertThat(highlight("public 1234", cloneTokenizer), is("<r>public</r> 1234"));
+ }
+
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/SyntaxHighlighterTestingHarness.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/SyntaxHighlighterTestingHarness.java
new file mode 100644
index 00000000000..882752e8bb9
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/SyntaxHighlighterTestingHarness.java
@@ -0,0 +1,11 @@
+package org.sonar.colorizer;
+
+import org.sonar.channel.Channel;
+
+public class SyntaxHighlighterTestingHarness {
+
+ public static String highlight(String input, Channel<HtmlCodeBuilder> tokenHighlighter) {
+ TokenizerDispatcher syntaxHighlighter = new TokenizerDispatcher(tokenHighlighter);
+ return syntaxHighlighter.colorize(input);
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/TokenizerDispatcherTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/TokenizerDispatcherTest.java
new file mode 100644
index 00000000000..c551b289e03
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/TokenizerDispatcherTest.java
@@ -0,0 +1,81 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.sonar.channel.Channel;
+import org.sonar.channel.CodeReader;
+
+public class TokenizerDispatcherTest {
+
+ @Test
+ public void testPipeCodeTokenizer() {
+ TokenizerDispatcher colorization = newColorizer();
+ assertThat(colorization.colorize("public void get(){"), is("public void get(){"));
+ }
+
+ @Test
+ public void testKeywordsCodeTokenizer() {
+ TokenizerDispatcher colorization = newColorizer(new KeywordsTokenizer("<k>", "</k>", JavaKeywords.get()));
+ assertThat(colorization.colorize("public void get(){"), is("<k>public</k> <k>void</k> get(){"));
+ }
+
+ @Test
+ public void testPriorityToComment() {
+ TokenizerDispatcher colorization = newColorizer(new CDocTokenizer("<c>", "</c>"), new KeywordsTokenizer("<k>", "</k>", JavaKeywords
+ .get()));
+ assertThat(colorization.colorize("assert //public void get(){"), is("<k>assert</k> <c>//public void get(){</c>"));
+ }
+
+ @Test
+ public void testCommentThenStringThenJavaKeywords() {
+ TokenizerDispatcher colorization = newColorizer(new CDocTokenizer("<c>", "</c>"), new LiteralTokenizer("<s>", "</s>"),
+ new KeywordsTokenizer("<k>", "</k>", JavaKeywords.get()));
+ assertThat(colorization.colorize("assert(\"message\"); //comment"), is("<k>assert</k>(<s>\"message\"</s>); <c>//comment</c>"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testCloneNotThreadSafeTokenizers() {
+ NotThreadSafeTokenizer tokenizer = new NotThreadSafeTokenizer() {
+
+ @Override
+ public boolean consume(CodeReader code, HtmlCodeBuilder output) {
+ output.append((char) code.pop());
+ return true;
+ }
+
+ @Override
+ public NotThreadSafeTokenizer clone() {
+ throw new IllegalStateException("The clone method has been called as expected.");
+ }
+ };
+ TokenizerDispatcher colorization = newColorizer(tokenizer);
+ colorization.colorize("source code");
+ }
+
+ private TokenizerDispatcher newColorizer(Channel<HtmlCodeBuilder>... tokenizers) {
+ return new TokenizerDispatcher(Arrays.asList(tokenizers));
+ }
+}
diff --git a/sonar-colorizer/src/test/java/org/sonar/colorizer/UserGuideTest.java b/sonar-colorizer/src/test/java/org/sonar/colorizer/UserGuideTest.java
new file mode 100644
index 00000000000..681e810c127
--- /dev/null
+++ b/sonar-colorizer/src/test/java/org/sonar/colorizer/UserGuideTest.java
@@ -0,0 +1,76 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.colorizer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Test;
+
+public class UserGuideTest {
+
+ @Test
+ public void javaToHtml() throws IOException {
+ Reader java = readFile("/org/sonar/colorizer/samples/Sample.java");
+
+ String html = CodeColorizer.javaToHtml(java, HtmlOptions.DEFAULT);
+
+ save(html, "Sample.java.html");
+ }
+
+ @Test
+ public void groovyToHtml() throws IOException {
+ Reader groovy = readFile("/org/sonar/colorizer/samples/Sample.groovy");
+
+ String html = CodeColorizer.groovyToHtml(groovy, HtmlOptions.DEFAULT);
+
+ save(html, "Sample.groovy.html");
+ }
+
+ @Test
+ public void customizeOutput() throws IOException {
+ Reader java = readFile("/org/sonar/colorizer/samples/Sample.java");
+
+ // generate only the <table> element, without including the CSS and the HTML header
+ HtmlOptions options = new HtmlOptions(true, "my-table-id", false);
+ String html = CodeColorizer.javaToHtml(java, options);
+
+ save(html, "CustomizeOutput.java.html");
+ }
+
+ @Test
+ public void defineNewLanguage() throws IOException {
+
+ }
+
+ private FileReader readFile(String path) throws FileNotFoundException {
+ return new FileReader(FileUtils.toFile(getClass().getResource(path)));
+ }
+
+ private void save(String html, String filename) throws IOException {
+ File output = new File("target/userguide/" + filename);
+ FileUtils.writeStringToFile(output, html);
+ System.out.println("HTML sample saved to: " + output.getAbsolutePath());
+ }
+}
diff --git a/sonar-colorizer/src/test/resources/org/sonar/colorizer/HtmlRendererTest/Sample.java b/sonar-colorizer/src/test/resources/org/sonar/colorizer/HtmlRendererTest/Sample.java
new file mode 100644
index 00000000000..6f8b935e1ae
--- /dev/null
+++ b/sonar-colorizer/src/test/resources/org/sonar/colorizer/HtmlRendererTest/Sample.java
@@ -0,0 +1,17 @@
+package org.sonar.colorizer.colorizer.HtmlRendererTest;
+
+public class Sample {
+
+ /**
+ * some javadoc
+ *
+ * @return foo
+ */
+ @Deprecated
+ public String foo(String bar) {
+ if (true) {
+ return "foo";
+ }
+ return "bar";
+ }
+} \ No newline at end of file
diff --git a/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.groovy b/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.groovy
new file mode 100644
index 00000000000..70de12a2e30
--- /dev/null
+++ b/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.groovy
@@ -0,0 +1,13 @@
+/**
+ comment
+ */
+@Deprecated
+class Greet {
+ def name
+ Greet(who) { name = who[0].toUpperCase() +
+ who[1..-1] }
+ def salute() { println "Hello $name!" }
+}
+
+g = new Greet('world') // create object
+g.salute() // Output "Hello World!"
diff --git a/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.java b/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.java
new file mode 100644
index 00000000000..f736b368147
--- /dev/null
+++ b/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/Sample.java
@@ -0,0 +1,52 @@
+package org.sonar.colorizer.samples;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.net.URL;
+
+/*
+ * NOT javadoc, for example license header
+*/
+public class Sample {
+
+ private static final double NUMBER = 3.1415;
+ private static final double INTEGER = 77;
+
+ /**
+ * some javadoc
+ *
+ * @return foo
+ */
+ @Deprecated
+ public String foo(String bar) {
+ // single-line comment
+ if (true) {
+ return "foo";
+ }
+
+ String backslashes = "";
+ backslashes.replaceAll("\\(", "(\"").replaceAll("\\)", "\")");
+
+ /*
+ Multi-lines comment
+ */
+ return "bar";
+ }
+
+ /**
+ * Special HTML characters in code : <code>foo</code>
+ */
+ public void specialHtmlCharacters() {
+ String special = "<html> <<";
+ }
+
+
+ public native void nativeMethod() /*-{
+ Window.alert('this is javascript');
+ }-*/;
+}
+
+@Target(ElementType.METHOD)
+ @interface Foo {
+
+} \ No newline at end of file
diff --git a/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/SingleLine.java b/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/SingleLine.java
new file mode 100644
index 00000000000..a9d082df1e6
--- /dev/null
+++ b/sonar-colorizer/src/test/resources/org/sonar/colorizer/samples/SingleLine.java
@@ -0,0 +1 @@
+package org.sonar.colorizer.samples; \ No newline at end of file