diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
commit | aeadc1f9129274949daaa57738c7c4550bdfbc7b (patch) | |
tree | 08dadf5ef7474fc41d1d48f74648f1ba8b55f34d /sonar-colorizer | |
download | sonarqube-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')
51 files changed, 2909 insertions, 0 deletions
diff --git a/sonar-colorizer/pom.xml b/sonar-colorizer/pom.xml new file mode 100644 index 00000000000..abca4773a36 --- /dev/null +++ b/sonar-colorizer/pom.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar</artifactId> + <version>2.3-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>sonar-colorizer</artifactId> + <packaging>jar</packaging> + <name>Sonar :: Code Colorizer</name> + <description>Code syntax highlighter</description> + + <dependencies> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-channel</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-all</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file 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("<"); + } else if (c == '>') { + colorizedCode.append(">"); + } 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 < olivier", builder.toString()); + } + + @Test + public void testAppendChar() { + builder.append('p'); + builder.append('a'); + builder.append('>'); + assertEquals("pa>", 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>\"<html>\"</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 |