aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-colorizer/src/main
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/main
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/main')
-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
27 files changed, 1621 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;
+}
+
+