diff --git a/src/main/java/org/sonar/plugins/scala/ScalaPlugin.java b/src/main/java/org/sonar/plugins/scala/ScalaPlugin.java index 259b1dd..93f2144 100644 --- a/src/main/java/org/sonar/plugins/scala/ScalaPlugin.java +++ b/src/main/java/org/sonar/plugins/scala/ScalaPlugin.java @@ -1,68 +1,68 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala; - -import java.util.ArrayList; -import java.util.List; - -import org.sonar.api.Extension; -import org.sonar.api.SonarPlugin; -import org.sonar.plugins.scala.colorization.ScalaColorizerFormat; -import org.sonar.plugins.scala.language.Scala; -import org.sonar.plugins.scala.sensor.BaseMetricsSensor; -import org.sonar.plugins.scala.surefire.SurefireSensor; - -/** - * This class is the entry point for all extensions made by the - * Sonar Scala Plugin. - * - * @author Felix Müller - * @since 0.1 - */ -public class ScalaPlugin extends SonarPlugin { - - public List> getExtensions() { - final List> extensions = new ArrayList>(); - extensions.add(Scala.class); - extensions.add(ScalaColorizerFormat.class); - extensions.add(BaseMetricsSensor.class); - extensions.add(SurefireSensor.class); - - return extensions; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - public static String getPathToScalaLibrary() { - return getPathByResource("scala/package.class"); - } - - /** - * Godin: during execution of Sonar Batch all dependencies of a plugin are downloaded and - * available locally as JAR-files, so we can use this kind of hack to locate JARs. - */ - private static String getPathByResource(String name) { - String path = ScalaPlugin.class.getClassLoader().getResource(name).getPath(); - return path.substring("file:".length(), path.lastIndexOf('!')); - } -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala; + +import java.util.ArrayList; +import java.util.List; + +import org.sonar.api.Extension; +import org.sonar.api.SonarPlugin; +import org.sonar.plugins.scala.colorization.ScalaColorizerFormat; +import org.sonar.plugins.scala.language.Scala; +import org.sonar.plugins.scala.sensor.BaseMetricsSensor; +import org.sonar.plugins.scala.surefire.SurefireSensor; + +/** + * This class is the entry point for all extensions made by the + * Sonar Scala Plugin. + * + * @author Felix Müller + * @since 0.1 + */ +public class ScalaPlugin extends SonarPlugin { + + public List> getExtensions() { + final List> extensions = new ArrayList>(); + extensions.add(Scala.class); + extensions.add(ScalaColorizerFormat.class); + extensions.add(BaseMetricsSensor.class); + extensions.add(SurefireSensor.class); + + return extensions; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + public static String getPathToScalaLibrary() { + return getPathByResource("scala/package.class"); + } + + /** + * Godin: during execution of Sonar Batch all dependencies of a plugin are downloaded and + * available locally as JAR-files, so we can use this kind of hack to locate JARs. + */ + private static String getPathByResource(String name) { + String path = ScalaPlugin.class.getClassLoader().getResource(name).getPath(); + return path.substring("file:".length(), path.lastIndexOf('!')); + } +} diff --git a/src/main/java/org/sonar/plugins/scala/colorization/ScalaColorizerFormat.java b/src/main/java/org/sonar/plugins/scala/colorization/ScalaColorizerFormat.java index 2ef770a..fec8307 100644 --- a/src/main/java/org/sonar/plugins/scala/colorization/ScalaColorizerFormat.java +++ b/src/main/java/org/sonar/plugins/scala/colorization/ScalaColorizerFormat.java @@ -1,62 +1,62 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.colorization; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.sonar.api.web.CodeColorizerFormat; -import org.sonar.colorizer.CDocTokenizer; -import org.sonar.colorizer.CppDocTokenizer; -import org.sonar.colorizer.JavaAnnotationTokenizer; -import org.sonar.colorizer.JavadocTokenizer; -import org.sonar.colorizer.KeywordsTokenizer; -import org.sonar.colorizer.LiteralTokenizer; -import org.sonar.colorizer.Tokenizer; -import org.sonar.plugins.scala.language.Scala; - -/** - * This class extends Sonar for code colorization of Scala source. - * - * @author Felix Müller - * @since 0.1 - */ -public class ScalaColorizerFormat extends CodeColorizerFormat { - - private static final String END_SPAN_TAG = ""; - - private static final List TOKENIZERS = Arrays.asList( - new LiteralTokenizer("", END_SPAN_TAG), - new KeywordsTokenizer("", END_SPAN_TAG, ScalaKeywords.getAllKeywords()), - new CDocTokenizer("", END_SPAN_TAG), - new CppDocTokenizer("", END_SPAN_TAG), - new JavadocTokenizer("", END_SPAN_TAG), - new JavaAnnotationTokenizer("", END_SPAN_TAG)); - - public ScalaColorizerFormat() { - super(Scala.KEY); - } - - @Override - public List getTokenizers() { - return Collections.unmodifiableList(TOKENIZERS); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.colorization; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.sonar.api.web.CodeColorizerFormat; +import org.sonar.colorizer.CDocTokenizer; +import org.sonar.colorizer.CppDocTokenizer; +import org.sonar.colorizer.JavaAnnotationTokenizer; +import org.sonar.colorizer.JavadocTokenizer; +import org.sonar.colorizer.KeywordsTokenizer; +import org.sonar.colorizer.LiteralTokenizer; +import org.sonar.colorizer.Tokenizer; +import org.sonar.plugins.scala.language.Scala; + +/** + * This class extends Sonar for code colorization of Scala source. + * + * @author Felix Müller + * @since 0.1 + */ +public class ScalaColorizerFormat extends CodeColorizerFormat { + + private static final String END_SPAN_TAG = ""; + + private static final List TOKENIZERS = Arrays.asList( + new LiteralTokenizer("", END_SPAN_TAG), + new KeywordsTokenizer("", END_SPAN_TAG, ScalaKeywords.getAllKeywords()), + new CDocTokenizer("", END_SPAN_TAG), + new CppDocTokenizer("", END_SPAN_TAG), + new JavadocTokenizer("", END_SPAN_TAG), + new JavaAnnotationTokenizer("", END_SPAN_TAG)); + + public ScalaColorizerFormat() { + super(Scala.KEY); + } + + @Override + public List getTokenizers() { + return Collections.unmodifiableList(TOKENIZERS); + } } \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/scala/colorization/ScalaKeywords.java b/src/main/java/org/sonar/plugins/scala/colorization/ScalaKeywords.java index fb209ea..ad149f3 100644 --- a/src/main/java/org/sonar/plugins/scala/colorization/ScalaKeywords.java +++ b/src/main/java/org/sonar/plugins/scala/colorization/ScalaKeywords.java @@ -1,50 +1,50 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.colorization; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * This is a helper class for collecting every Scala keyword. - * - * @author Felix Müller - * @since 0.1 - */ -public final class ScalaKeywords { - - private static final Set KEYWORDS = new HashSet(Arrays.asList( - "abstract", "assert", "case", "catch", "class", "def", "do", "else", "extends", "false", - "final", "finally", "for", "forSome", "if", "implicit", "import", "lazy", "match", "new", - "null", "object", "override", "package", "private", "protected", "requires", "return", - "sealed", "super", "this", "throw", "trait", "true", "try", "type", "val", "var", "while", - "with", "yield", "_", ":", "=", "=>", "<-", "<:", "<%", ">:", "#", "@" - )); - - private ScalaKeywords() { - // to prevent instantiation - } - - public static Set getAllKeywords() { - return Collections.unmodifiableSet(KEYWORDS); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.colorization; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * This is a helper class for collecting every Scala keyword. + * + * @author Felix Müller + * @since 0.1 + */ +public final class ScalaKeywords { + + private static final Set KEYWORDS = new HashSet(Arrays.asList( + "abstract", "assert", "case", "catch", "class", "def", "do", "else", "extends", "false", + "final", "finally", "for", "forSome", "if", "implicit", "import", "lazy", "match", "new", + "null", "object", "override", "package", "private", "protected", "requires", "return", + "sealed", "super", "this", "throw", "trait", "true", "try", "type", "val", "var", "while", + "with", "yield", "_", ":", "=", "=>", "<-", "<:", "<%", ">:", "#", "@" + )); + + private ScalaKeywords() { + // to prevent instantiation + } + + public static Set getAllKeywords() { + return Collections.unmodifiableSet(KEYWORDS); + } } \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/scala/cpd/ScalaCpdMapping.java b/src/main/java/org/sonar/plugins/scala/cpd/ScalaCpdMapping.java index 01dc500..e478fde 100644 --- a/src/main/java/org/sonar/plugins/scala/cpd/ScalaCpdMapping.java +++ b/src/main/java/org/sonar/plugins/scala/cpd/ScalaCpdMapping.java @@ -1,50 +1,50 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.cpd; - -import net.sourceforge.pmd.cpd.Tokenizer; - -import org.sonar.api.batch.AbstractCpdMapping; -import org.sonar.api.resources.Language; - -import org.sonar.plugins.scala.language.Scala; - -/** - * Glue Sonar and PMD CPD together. - * - * @since 0.1 - */ -public class ScalaCpdMapping extends AbstractCpdMapping { - - private final Scala scala; - - public ScalaCpdMapping(Scala scala) { - this.scala = scala; - } - - public Tokenizer getTokenizer() { - return new ScalaTokenizer(); - } - - public Language getLanguage() { - return scala; - } - -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.cpd; + +import net.sourceforge.pmd.cpd.Tokenizer; + +import org.sonar.api.batch.AbstractCpdMapping; +import org.sonar.api.resources.Language; + +import org.sonar.plugins.scala.language.Scala; + +/** + * Glue Sonar and PMD CPD together. + * + * @since 0.1 + */ +public class ScalaCpdMapping extends AbstractCpdMapping { + + private final Scala scala; + + public ScalaCpdMapping(Scala scala) { + this.scala = scala; + } + + public Tokenizer getTokenizer() { + return new ScalaTokenizer(); + } + + public Language getLanguage() { + return scala; + } + +} diff --git a/src/main/java/org/sonar/plugins/scala/cpd/ScalaTokenizer.java b/src/main/java/org/sonar/plugins/scala/cpd/ScalaTokenizer.java index 034c3f5..f5fd5cf 100644 --- a/src/main/java/org/sonar/plugins/scala/cpd/ScalaTokenizer.java +++ b/src/main/java/org/sonar/plugins/scala/cpd/ScalaTokenizer.java @@ -1,52 +1,52 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.cpd; - -import java.util.List; - -import net.sourceforge.pmd.cpd.SourceCode; -import net.sourceforge.pmd.cpd.TokenEntry; -import net.sourceforge.pmd.cpd.Tokenizer; -import net.sourceforge.pmd.cpd.Tokens; - -import org.sonar.plugins.scala.compiler.Lexer; -import org.sonar.plugins.scala.compiler.Token; - -/** - * Scala tokenizer for PMD CPD. - * - * @since 0.1 - */ -public final class ScalaTokenizer implements Tokenizer { - - public void tokenize(SourceCode source, Tokens cpdTokens) { - String filename = source.getFileName(); - - Lexer lexer = new Lexer(); - List tokens = lexer.getTokensOfFile(filename); - for (Token token : tokens) { - TokenEntry cpdToken = new TokenEntry(Integer.toString(token.tokenType()), filename, token.line()); - cpdTokens.add(cpdToken); - } - - cpdTokens.add(TokenEntry.getEOF()); - } - -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.cpd; + +import java.util.List; + +import net.sourceforge.pmd.cpd.SourceCode; +import net.sourceforge.pmd.cpd.TokenEntry; +import net.sourceforge.pmd.cpd.Tokenizer; +import net.sourceforge.pmd.cpd.Tokens; + +import org.sonar.plugins.scala.compiler.Lexer; +import org.sonar.plugins.scala.compiler.Token; + +/** + * Scala tokenizer for PMD CPD. + * + * @since 0.1 + */ +public final class ScalaTokenizer implements Tokenizer { + + public void tokenize(SourceCode source, Tokens cpdTokens) { + String filename = source.getFileName(); + + Lexer lexer = new Lexer(); + List tokens = lexer.getTokensOfFile(filename); + for (Token token : tokens) { + TokenEntry cpdToken = new TokenEntry(Integer.toString(token.tokenType()), filename, token.line()); + cpdTokens.add(cpdToken); + } + + cpdTokens.add(TokenEntry.getEOF()); + } + +} diff --git a/src/main/java/org/sonar/plugins/scala/language/Comment.java b/src/main/java/org/sonar/plugins/scala/language/Comment.java index fb4002b..58125ed 100644 --- a/src/main/java/org/sonar/plugins/scala/language/Comment.java +++ b/src/main/java/org/sonar/plugins/scala/language/Comment.java @@ -1,119 +1,119 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language; - -import java.io.IOException; -import java.util.List; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.sonar.plugins.scala.util.StringUtils; - -/** - * This class implements a Scala comment and the computation - * of several base metrics for a comment. - * - * @author Felix Müller - * @since 0.1 - */ -public class Comment { - - private final CommentType type; - private final List lines; - - public Comment(String content, CommentType type) throws IOException { - lines = StringUtils.convertStringToListOfLines(content); - this.type = type; - } - - public int getNumberOfLines() { - return lines.size() - getNumberOfBlankLines() - getNumberOfCommentedOutLinesOfCode(); - } - - public int getNumberOfBlankLines() { - int numberOfBlankLines = 0; - for (String comment : lines) { - boolean isBlank = true; - - for (int i = 0; isBlank && i < comment.length(); i++) { - char character = comment.charAt(i); - if (!Character.isWhitespace(character) && character != '*' && character != '/') { - isBlank = false; - } - } - - if (isBlank) { - numberOfBlankLines++; - } - } - return numberOfBlankLines; - } - - public int getNumberOfCommentedOutLinesOfCode() { - if (isDocComment()) { - return 0; - } - - int numberOfCommentedOutLinesOfCode = 0; - for (String line : lines) { - String strippedLine = org.apache.commons.lang.StringUtils.strip(line, " /*"); - if (CodeDetector.hasDetectedCode(strippedLine)) { - numberOfCommentedOutLinesOfCode++; - } - } - return numberOfCommentedOutLinesOfCode; - } - - public boolean isDocComment() { - return type == CommentType.DOC; - } - - public boolean isHeaderComment() { - return type == CommentType.HEADER; - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(type).append(lines).toHashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Comment)) { - return false; - } - - Comment other = (Comment) obj; - return new EqualsBuilder().append(type, other.type).append(lines, other.lines).isEquals(); - } - - @Override - public String toString() { - final String firstLine = lines.isEmpty() ? "" : lines.get(0); - final String lastLine = lines.isEmpty() ? "" : lines.get(lines.size() - 1); - return new ToStringBuilder(this).append("type", type) - .append("firstLine", firstLine) - .append("lastLine", lastLine) - .append("numberOfLines", getNumberOfLines()) - .append("numberOfCommentedOutLinesOfCode", getNumberOfCommentedOutLinesOfCode()) - .toString(); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language; + +import java.io.IOException; +import java.util.List; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.plugins.scala.util.StringUtils; + +/** + * This class implements a Scala comment and the computation + * of several base metrics for a comment. + * + * @author Felix Müller + * @since 0.1 + */ +public class Comment { + + private final CommentType type; + private final List lines; + + public Comment(String content, CommentType type) throws IOException { + lines = StringUtils.convertStringToListOfLines(content); + this.type = type; + } + + public int getNumberOfLines() { + return lines.size() - getNumberOfBlankLines() - getNumberOfCommentedOutLinesOfCode(); + } + + public int getNumberOfBlankLines() { + int numberOfBlankLines = 0; + for (String comment : lines) { + boolean isBlank = true; + + for (int i = 0; isBlank && i < comment.length(); i++) { + char character = comment.charAt(i); + if (!Character.isWhitespace(character) && character != '*' && character != '/') { + isBlank = false; + } + } + + if (isBlank) { + numberOfBlankLines++; + } + } + return numberOfBlankLines; + } + + public int getNumberOfCommentedOutLinesOfCode() { + if (isDocComment()) { + return 0; + } + + int numberOfCommentedOutLinesOfCode = 0; + for (String line : lines) { + String strippedLine = org.apache.commons.lang.StringUtils.strip(line, " /*"); + if (CodeDetector.hasDetectedCode(strippedLine)) { + numberOfCommentedOutLinesOfCode++; + } + } + return numberOfCommentedOutLinesOfCode; + } + + public boolean isDocComment() { + return type == CommentType.DOC; + } + + public boolean isHeaderComment() { + return type == CommentType.HEADER; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(type).append(lines).toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Comment)) { + return false; + } + + Comment other = (Comment) obj; + return new EqualsBuilder().append(type, other.type).append(lines, other.lines).isEquals(); + } + + @Override + public String toString() { + final String firstLine = lines.isEmpty() ? "" : lines.get(0); + final String lastLine = lines.isEmpty() ? "" : lines.get(lines.size() - 1); + return new ToStringBuilder(this).append("type", type) + .append("firstLine", firstLine) + .append("lastLine", lastLine) + .append("numberOfLines", getNumberOfLines()) + .append("numberOfCommentedOutLinesOfCode", getNumberOfCommentedOutLinesOfCode()) + .toString(); + } } \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/scala/language/CommentType.java b/src/main/java/org/sonar/plugins/scala/language/CommentType.java index e4a2a03..bf0b19d 100644 --- a/src/main/java/org/sonar/plugins/scala/language/CommentType.java +++ b/src/main/java/org/sonar/plugins/scala/language/CommentType.java @@ -1,34 +1,34 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language; - -/** - * This enum is a helper to distinguish between the - * different types of comments in Sonar. - * - * @author Felix Müller - * @since 0.1 - */ -public enum CommentType { - - NORMAL, - DOC, - HEADER; +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language; + +/** + * This enum is a helper to distinguish between the + * different types of comments in Sonar. + * + * @author Felix Müller + * @since 0.1 + */ +public enum CommentType { + + NORMAL, + DOC, + HEADER; } \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/scala/language/Scala.java b/src/main/java/org/sonar/plugins/scala/language/Scala.java index 78c8353..cfa72f9 100644 --- a/src/main/java/org/sonar/plugins/scala/language/Scala.java +++ b/src/main/java/org/sonar/plugins/scala/language/Scala.java @@ -1,47 +1,47 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language; - -import org.sonar.api.config.Settings; -import org.sonar.api.resources.AbstractLanguage; - -/** - * This class implements Scala as a language for Sonar. - * - * @author Felix Müller - * @since 0.1 - */ -public class Scala extends AbstractLanguage { - - public static final String KEY = "scala"; - public static final String NAME = "Scala"; - - private final Settings settings; - - - public Scala(Settings settings) { - super(KEY, NAME); - this.settings = settings; - } - - public String[] getFileSuffixes() { - return new String[] { "scala" }; - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language; + +import org.sonar.api.config.Settings; +import org.sonar.api.resources.AbstractLanguage; + +/** + * This class implements Scala as a language for Sonar. + * + * @author Felix Müller + * @since 0.1 + */ +public class Scala extends AbstractLanguage { + + public static final String KEY = "scala"; + public static final String NAME = "Scala"; + + private final Settings settings; + + + public Scala(Settings settings) { + super(KEY, NAME); + this.settings = settings; + } + + public String[] getFileSuffixes() { + return new String[] { "scala" }; + } } \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/scala/metrics/LinesAnalyzer.java b/src/main/java/org/sonar/plugins/scala/metrics/LinesAnalyzer.java index 3a8d446..f67af96 100644 --- a/src/main/java/org/sonar/plugins/scala/metrics/LinesAnalyzer.java +++ b/src/main/java/org/sonar/plugins/scala/metrics/LinesAnalyzer.java @@ -1,61 +1,61 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics; - -import java.util.List; - -import org.apache.commons.lang.StringUtils; - -/** - * This class implements the computation of basic - * line metrics for a {@link ScalaFile}. - * - * @author Felix Müller - * @since 0.1 - */ -public class LinesAnalyzer { - - private final List lines; - private final CommentsAnalyzer commentsAnalyzer; - - public LinesAnalyzer(List lines, CommentsAnalyzer commentsAnalyzer) { - this.lines = lines; - this.commentsAnalyzer = commentsAnalyzer; - } - - public int countLines() { - return lines.size(); - } - - public int countLinesOfCode() { - return countLines() - countBlankLines() - commentsAnalyzer.countCommentLines() - - commentsAnalyzer.countHeaderCommentLines() - commentsAnalyzer.countBlankCommentLines(); - } - - private int countBlankLines() { - int numberOfBlankLines = 0; - for (String line : lines) { - if (StringUtils.isBlank(line)) { - numberOfBlankLines++; - } - } - return numberOfBlankLines; - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics; + +import java.util.List; + +import org.apache.commons.lang.StringUtils; + +/** + * This class implements the computation of basic + * line metrics for a {@link ScalaFile}. + * + * @author Felix Müller + * @since 0.1 + */ +public class LinesAnalyzer { + + private final List lines; + private final CommentsAnalyzer commentsAnalyzer; + + public LinesAnalyzer(List lines, CommentsAnalyzer commentsAnalyzer) { + this.lines = lines; + this.commentsAnalyzer = commentsAnalyzer; + } + + public int countLines() { + return lines.size(); + } + + public int countLinesOfCode() { + return countLines() - countBlankLines() - commentsAnalyzer.countCommentLines() + - commentsAnalyzer.countHeaderCommentLines() - commentsAnalyzer.countBlankCommentLines(); + } + + private int countBlankLines() { + int numberOfBlankLines = 0; + for (String line : lines) { + if (StringUtils.isBlank(line)) { + numberOfBlankLines++; + } + } + return numberOfBlankLines; + } } \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/scala/sensor/AbstractScalaSensor.java b/src/main/java/org/sonar/plugins/scala/sensor/AbstractScalaSensor.java index 4e1bb40..90b475b 100644 --- a/src/main/java/org/sonar/plugins/scala/sensor/AbstractScalaSensor.java +++ b/src/main/java/org/sonar/plugins/scala/sensor/AbstractScalaSensor.java @@ -1,50 +1,50 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.sensor; - -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.resources.Project; -import org.sonar.plugins.scala.language.Scala; - -/** - * This is a helper base class for sensors that should only be executed on Scala projects. - * - * @author Felix Müller - * @since 0.1 - */ -public abstract class AbstractScalaSensor implements Sensor { - - private final Scala scala; - protected final FileSystem fileSystem; - - protected AbstractScalaSensor(Scala scala, FileSystem fileSystem) { - this.scala = scala; - this.fileSystem = fileSystem; - } - - public final boolean shouldExecuteOnProject(Project project) { - return fileSystem.languages().contains(Scala.KEY); - } - - public final Scala getScala() { - return scala; - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.sensor; + +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.resources.Project; +import org.sonar.plugins.scala.language.Scala; + +/** + * This is a helper base class for sensors that should only be executed on Scala projects. + * + * @author Felix Müller + * @since 0.1 + */ +public abstract class AbstractScalaSensor implements Sensor { + + private final Scala scala; + protected final FileSystem fileSystem; + + protected AbstractScalaSensor(Scala scala, FileSystem fileSystem) { + this.scala = scala; + this.fileSystem = fileSystem; + } + + public final boolean shouldExecuteOnProject(Project project) { + return fileSystem.languages().contains(Scala.KEY); + } + + public final Scala getScala() { + return scala; + } } \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/scala/sensor/BaseMetricsSensor.java b/src/main/java/org/sonar/plugins/scala/sensor/BaseMetricsSensor.java index 9f471e3..3981482 100644 --- a/src/main/java/org/sonar/plugins/scala/sensor/BaseMetricsSensor.java +++ b/src/main/java/org/sonar/plugins/scala/sensor/BaseMetricsSensor.java @@ -1,141 +1,141 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.sensor; - -import java.io.IOException; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.batch.fs.FilePredicates; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.resources.Project; -import org.sonar.plugins.scala.compiler.Lexer; -import org.sonar.plugins.scala.language.Comment; -import org.sonar.plugins.scala.language.Scala; -import org.sonar.plugins.scala.metrics.CommentsAnalyzer; -import org.sonar.plugins.scala.metrics.ComplexityCalculator; -import org.sonar.plugins.scala.metrics.FunctionCounter; -import org.sonar.plugins.scala.metrics.LinesAnalyzer; -import org.sonar.plugins.scala.metrics.PublicApiCounter; -import org.sonar.plugins.scala.metrics.StatementCounter; -import org.sonar.plugins.scala.metrics.TypeCounter; -import org.sonar.plugins.scala.util.MetricDistribution; -import org.sonar.plugins.scala.util.StringUtils; - -/** - * This is the main sensor of the Scala plugin. It gathers all results - * of the computation of base metrics for all Scala resources. - * - * @author Felix Müller - * @since 0.1 - */ -public class BaseMetricsSensor extends AbstractScalaSensor { - - private static final Logger LOGGER = LoggerFactory.getLogger(BaseMetricsSensor.class); - - public BaseMetricsSensor(Scala scala, FileSystem fileSystem) { - super(scala, fileSystem); - } - - public void analyse(Project project, SensorContext sensorContext) { - final String charset = fileSystem.encoding().toString(); - - MetricDistribution complexityOfFunctions = null; - FilePredicates filePredicates = fileSystem.predicates(); - - for (InputFile inputFile : fileSystem.inputFiles(filePredicates.and(filePredicates.hasLanguage(Scala.KEY), filePredicates.hasType(InputFile.Type.MAIN)))) { - - sensorContext.saveMeasure(inputFile, CoreMetrics.FILES, 1.0); - - try { - final String source = FileUtils.readFileToString(inputFile.file(), charset); - final List lines = StringUtils.convertStringToListOfLines(source); - final List comments = new Lexer().getComments(source); - - final CommentsAnalyzer commentsAnalyzer = new CommentsAnalyzer(comments); - final LinesAnalyzer linesAnalyzer = new LinesAnalyzer(lines, commentsAnalyzer); - - addLineMetrics(sensorContext, inputFile, linesAnalyzer); - addCommentMetrics(sensorContext, inputFile, commentsAnalyzer); - addCodeMetrics(sensorContext, inputFile, source); - addPublicApiMetrics(sensorContext, inputFile, source); - - complexityOfFunctions = sumUpMetricDistributions(complexityOfFunctions, - ComplexityCalculator.measureComplexityOfFunctions(source)); - - } catch (IOException ioe) { - LOGGER.error("Could not read the file: " + inputFile.absolutePath(), ioe); - } - } - - if (complexityOfFunctions != null) - sensorContext.saveMeasure(complexityOfFunctions.getMeasure()); - - } - - private void addLineMetrics(SensorContext sensorContext, InputFile scalaFile, LinesAnalyzer linesAnalyzer) { - sensorContext.saveMeasure(scalaFile, CoreMetrics.LINES, (double) linesAnalyzer.countLines()); - sensorContext.saveMeasure(scalaFile, CoreMetrics.NCLOC, (double) linesAnalyzer.countLinesOfCode()); - } - - private void addCommentMetrics(SensorContext sensorContext, InputFile scalaFile, - CommentsAnalyzer commentsAnalyzer) { - sensorContext.saveMeasure(scalaFile, CoreMetrics.COMMENT_LINES, - (double) commentsAnalyzer.countCommentLines()); - } - - private void addCodeMetrics(SensorContext sensorContext, InputFile scalaFile, String source) { - sensorContext.saveMeasure(scalaFile, CoreMetrics.CLASSES, - (double) TypeCounter.countTypes(source)); - sensorContext.saveMeasure(scalaFile, CoreMetrics.STATEMENTS, - (double) StatementCounter.countStatements(source)); - sensorContext.saveMeasure(scalaFile, CoreMetrics.FUNCTIONS, - (double) FunctionCounter.countFunctions(source)); - sensorContext.saveMeasure(scalaFile, CoreMetrics.COMPLEXITY, - (double) ComplexityCalculator.measureComplexity(source)); - } - - private void addPublicApiMetrics(SensorContext sensorContext, InputFile scalaFile, String source) { - sensorContext.saveMeasure(scalaFile, CoreMetrics.PUBLIC_API, - (double) PublicApiCounter.countPublicApi(source)); - sensorContext.saveMeasure(scalaFile, CoreMetrics.PUBLIC_UNDOCUMENTED_API, - (double) PublicApiCounter.countUndocumentedPublicApi(source)); - } - - private MetricDistribution sumUpMetricDistributions(MetricDistribution oldDistribution, - MetricDistribution newDistribution) { - if (oldDistribution == null) { - return newDistribution; - } - - oldDistribution.add(newDistribution); - return oldDistribution; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.sensor; + +import java.io.IOException; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.resources.Project; +import org.sonar.plugins.scala.compiler.Lexer; +import org.sonar.plugins.scala.language.Comment; +import org.sonar.plugins.scala.language.Scala; +import org.sonar.plugins.scala.metrics.CommentsAnalyzer; +import org.sonar.plugins.scala.metrics.ComplexityCalculator; +import org.sonar.plugins.scala.metrics.FunctionCounter; +import org.sonar.plugins.scala.metrics.LinesAnalyzer; +import org.sonar.plugins.scala.metrics.PublicApiCounter; +import org.sonar.plugins.scala.metrics.StatementCounter; +import org.sonar.plugins.scala.metrics.TypeCounter; +import org.sonar.plugins.scala.util.MetricDistribution; +import org.sonar.plugins.scala.util.StringUtils; + +/** + * This is the main sensor of the Scala plugin. It gathers all results + * of the computation of base metrics for all Scala resources. + * + * @author Felix Müller + * @since 0.1 + */ +public class BaseMetricsSensor extends AbstractScalaSensor { + + private static final Logger LOGGER = LoggerFactory.getLogger(BaseMetricsSensor.class); + + public BaseMetricsSensor(Scala scala, FileSystem fileSystem) { + super(scala, fileSystem); + } + + public void analyse(Project project, SensorContext sensorContext) { + final String charset = fileSystem.encoding().toString(); + + MetricDistribution complexityOfFunctions = null; + FilePredicates filePredicates = fileSystem.predicates(); + + for (InputFile inputFile : fileSystem.inputFiles(filePredicates.and(filePredicates.hasLanguage(Scala.KEY), filePredicates.hasType(InputFile.Type.MAIN)))) { + + sensorContext.saveMeasure(inputFile, CoreMetrics.FILES, 1.0); + + try { + final String source = FileUtils.readFileToString(inputFile.file(), charset); + final List lines = StringUtils.convertStringToListOfLines(source); + final List comments = new Lexer().getComments(source); + + final CommentsAnalyzer commentsAnalyzer = new CommentsAnalyzer(comments); + final LinesAnalyzer linesAnalyzer = new LinesAnalyzer(lines, commentsAnalyzer); + + addLineMetrics(sensorContext, inputFile, linesAnalyzer); + addCommentMetrics(sensorContext, inputFile, commentsAnalyzer); + addCodeMetrics(sensorContext, inputFile, source); + addPublicApiMetrics(sensorContext, inputFile, source); + + complexityOfFunctions = sumUpMetricDistributions(complexityOfFunctions, + ComplexityCalculator.measureComplexityOfFunctions(source)); + + } catch (IOException ioe) { + LOGGER.error("Could not read the file: " + inputFile.absolutePath(), ioe); + } + } + + if (complexityOfFunctions != null) + sensorContext.saveMeasure(complexityOfFunctions.getMeasure()); + + } + + private void addLineMetrics(SensorContext sensorContext, InputFile scalaFile, LinesAnalyzer linesAnalyzer) { + sensorContext.saveMeasure(scalaFile, CoreMetrics.LINES, (double) linesAnalyzer.countLines()); + sensorContext.saveMeasure(scalaFile, CoreMetrics.NCLOC, (double) linesAnalyzer.countLinesOfCode()); + } + + private void addCommentMetrics(SensorContext sensorContext, InputFile scalaFile, + CommentsAnalyzer commentsAnalyzer) { + sensorContext.saveMeasure(scalaFile, CoreMetrics.COMMENT_LINES, + (double) commentsAnalyzer.countCommentLines()); + } + + private void addCodeMetrics(SensorContext sensorContext, InputFile scalaFile, String source) { + sensorContext.saveMeasure(scalaFile, CoreMetrics.CLASSES, + (double) TypeCounter.countTypes(source)); + sensorContext.saveMeasure(scalaFile, CoreMetrics.STATEMENTS, + (double) StatementCounter.countStatements(source)); + sensorContext.saveMeasure(scalaFile, CoreMetrics.FUNCTIONS, + (double) FunctionCounter.countFunctions(source)); + sensorContext.saveMeasure(scalaFile, CoreMetrics.COMPLEXITY, + (double) ComplexityCalculator.measureComplexity(source)); + } + + private void addPublicApiMetrics(SensorContext sensorContext, InputFile scalaFile, String source) { + sensorContext.saveMeasure(scalaFile, CoreMetrics.PUBLIC_API, + (double) PublicApiCounter.countPublicApi(source)); + sensorContext.saveMeasure(scalaFile, CoreMetrics.PUBLIC_UNDOCUMENTED_API, + (double) PublicApiCounter.countUndocumentedPublicApi(source)); + } + + private MetricDistribution sumUpMetricDistributions(MetricDistribution oldDistribution, + MetricDistribution newDistribution) { + if (oldDistribution == null) { + return newDistribution; + } + + oldDistribution.add(newDistribution); + return oldDistribution; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } } \ No newline at end of file diff --git a/src/main/scala/org/sonar/plugins/scala/compiler/Compiler.scala b/src/main/scala/org/sonar/plugins/scala/compiler/Compiler.scala index bce5db2..e8e7af8 100644 --- a/src/main/scala/org/sonar/plugins/scala/compiler/Compiler.scala +++ b/src/main/scala/org/sonar/plugins/scala/compiler/Compiler.scala @@ -1,49 +1,49 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.compiler - -import scala.tools.nsc.{Settings, Global} -import org.slf4j.LoggerFactory -import java.net.URI - -/** - * This is a wrapper for the Scala compiler. It is used to access - * the compiler in a more convenient way. - * - * @author Felix Müller - * @since 0.1 - */ -object Compiler extends Global(new Settings() { - - val path = new URI(org.sonar.plugins.scala.ScalaPlugin.getPathToScalaLibrary).getPath() - bootclasspath.append(path) - -}) { - - private val logger = LoggerFactory.getLogger(classOf[Compiler]) - - try { - new Run() - } catch { - case ex: Throwable => logger.error("Could not initiate Scala compiler, probably due classpath issues!", ex) - } - - override def forScaladoc = true -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.compiler + +import scala.tools.nsc.{Settings, Global} +import org.slf4j.LoggerFactory +import java.net.URI + +/** + * This is a wrapper for the Scala compiler. It is used to access + * the compiler in a more convenient way. + * + * @author Felix Müller + * @since 0.1 + */ +object Compiler extends Global(new Settings() { + + val path = new URI(org.sonar.plugins.scala.ScalaPlugin.getPathToScalaLibrary).getPath() + bootclasspath.append(path) + +}) { + + private val logger = LoggerFactory.getLogger(classOf[Compiler]) + + try { + new Run() + } catch { + case ex: Throwable => logger.error("Could not initiate Scala compiler, probably due classpath issues!", ex) + } + + override def forScaladoc = true +} diff --git a/src/main/scala/org/sonar/plugins/scala/compiler/Lexer.scala b/src/main/scala/org/sonar/plugins/scala/compiler/Lexer.scala index 13016d9..360cbad 100644 --- a/src/main/scala/org/sonar/plugins/scala/compiler/Lexer.scala +++ b/src/main/scala/org/sonar/plugins/scala/compiler/Lexer.scala @@ -1,124 +1,124 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.compiler - -import collection.mutable.ListBuffer - -import org.sonar.plugins.scala.language.{Comment, CommentType} -import scala.reflect.io.AbstractFile -import scala.reflect.internal.util.BatchSourceFile - -/** - * This class is a wrapper for accessing the lexer of the Scala compiler - * from Java in a more convenient way. - * - * @author Felix Müller - * @since 0.1 - */ -class Lexer { - - import scala.collection.JavaConversions._ - import Compiler._ - - def getTokens(code: String): java.util.List[Token] = { - val unit = new CompilationUnit(new BatchSourceFile("", code.toCharArray)) - tokenize(unit) - } - - def getTokensOfFile(path: String): java.util.List[Token] = { - val unit = new CompilationUnit(new BatchSourceFile(AbstractFile.getFile(path))) - tokenize(unit) - } - - private def tokenize(unit: CompilationUnit): java.util.List[Token] = { - val scanner = new syntaxAnalyzer.UnitScanner(unit) - val tokens = ListBuffer[Token]() - - scanner.init() - while (scanner.token != scala.tools.nsc.ast.parser.Tokens.EOF) { - tokens += Token(scanner.token, scanner.parensAnalyzer.line(scanner.offset) + 1) - scanner.nextToken() - } - tokens - } - - def getComments(code: String): java.util.List[Comment] = { - val unit = new CompilationUnit(new BatchSourceFile("", code.toCharArray)) - tokenizeComments(unit) - } - - def getCommentsOfFile(path: String): java.util.List[Comment] = { - val unit = new CompilationUnit(new BatchSourceFile(AbstractFile.getFile(path))) - tokenizeComments(unit) - } - - private def tokenizeComments(unit: CompilationUnit): java.util.List[Comment] = { - val comments = ListBuffer[Comment]() - val scanner = new syntaxAnalyzer.UnitScanner(unit) { - - private var lastDocCommentRange: Option[Range] = None - - private var foundToken = false - - override def nextToken() { - super.nextToken() - foundToken = token != 0 - } - - override def foundComment(value: String, start: Int, end: Int) = { - super.foundComment(value, start, end) - - def isHeaderComment(value: String) = { - !foundToken && comments.isEmpty && value.trim().startsWith("/*") - } - - lastDocCommentRange match { - - case Some(r: Range) => { - if (r.start != start || r.end != end) { - comments += new Comment(value, CommentType.NORMAL) - } - } - - case None => { - if (isHeaderComment(value)) { - comments += new Comment(value, CommentType.HEADER) - } else { - comments += new Comment(value, CommentType.NORMAL) - } - } - } - } - - override def foundDocComment(value: String, start: Int, end: Int) = { - super.foundDocComment(value, start, end) - comments += new Comment(value, CommentType.DOC) - lastDocCommentRange = Some(Range(start, end)) - } - } - - scanner.init() - while (scanner.token != scala.tools.nsc.ast.parser.Tokens.EOF) { - scanner.nextToken() - } - - comments - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.compiler + +import collection.mutable.ListBuffer + +import org.sonar.plugins.scala.language.{Comment, CommentType} +import scala.reflect.io.AbstractFile +import scala.reflect.internal.util.BatchSourceFile + +/** + * This class is a wrapper for accessing the lexer of the Scala compiler + * from Java in a more convenient way. + * + * @author Felix Müller + * @since 0.1 + */ +class Lexer { + + import scala.collection.JavaConversions._ + import Compiler._ + + def getTokens(code: String): java.util.List[Token] = { + val unit = new CompilationUnit(new BatchSourceFile("", code.toCharArray)) + tokenize(unit) + } + + def getTokensOfFile(path: String): java.util.List[Token] = { + val unit = new CompilationUnit(new BatchSourceFile(AbstractFile.getFile(path))) + tokenize(unit) + } + + private def tokenize(unit: CompilationUnit): java.util.List[Token] = { + val scanner = new syntaxAnalyzer.UnitScanner(unit) + val tokens = ListBuffer[Token]() + + scanner.init() + while (scanner.token != scala.tools.nsc.ast.parser.Tokens.EOF) { + tokens += Token(scanner.token, scanner.parensAnalyzer.line(scanner.offset) + 1) + scanner.nextToken() + } + tokens + } + + def getComments(code: String): java.util.List[Comment] = { + val unit = new CompilationUnit(new BatchSourceFile("", code.toCharArray)) + tokenizeComments(unit) + } + + def getCommentsOfFile(path: String): java.util.List[Comment] = { + val unit = new CompilationUnit(new BatchSourceFile(AbstractFile.getFile(path))) + tokenizeComments(unit) + } + + private def tokenizeComments(unit: CompilationUnit): java.util.List[Comment] = { + val comments = ListBuffer[Comment]() + val scanner = new syntaxAnalyzer.UnitScanner(unit) { + + private var lastDocCommentRange: Option[Range] = None + + private var foundToken = false + + override def nextToken() { + super.nextToken() + foundToken = token != 0 + } + + override def foundComment(value: String, start: Int, end: Int) = { + super.foundComment(value, start, end) + + def isHeaderComment(value: String) = { + !foundToken && comments.isEmpty && value.trim().startsWith("/*") + } + + lastDocCommentRange match { + + case Some(r: Range) => { + if (r.start != start || r.end != end) { + comments += new Comment(value, CommentType.NORMAL) + } + } + + case None => { + if (isHeaderComment(value)) { + comments += new Comment(value, CommentType.HEADER) + } else { + comments += new Comment(value, CommentType.NORMAL) + } + } + } + } + + override def foundDocComment(value: String, start: Int, end: Int) = { + super.foundDocComment(value, start, end) + comments += new Comment(value, CommentType.DOC) + lastDocCommentRange = Some(Range(start, end)) + } + } + + scanner.init() + while (scanner.token != scala.tools.nsc.ast.parser.Tokens.EOF) { + scanner.nextToken() + } + + comments + } } \ No newline at end of file diff --git a/src/main/scala/org/sonar/plugins/scala/compiler/Parser.scala b/src/main/scala/org/sonar/plugins/scala/compiler/Parser.scala index 43cf48c..9355087 100644 --- a/src/main/scala/org/sonar/plugins/scala/compiler/Parser.scala +++ b/src/main/scala/org/sonar/plugins/scala/compiler/Parser.scala @@ -1,61 +1,61 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.compiler - -import scala.reflect.internal.util.{ScriptSourceFile, BatchSourceFile} -import scala.reflect.io.AbstractFile - -/** - * This class is a wrapper for accessing the parser of the Scala compiler - * from Java in a more convenient way. - * - * @author Felix Müller - * @since 0.1 - */ -class Parser { - - import Compiler._ - - def parse(code: String): Tree = { - val batchSourceFile = new BatchSourceFile("", code.toCharArray) - parse(batchSourceFile, code.toCharArray) - } - - def parseFile(path: String): Tree = { - val batchSourceFile = new BatchSourceFile(AbstractFile.getFile(path)) - parse(batchSourceFile, batchSourceFile.content.array) - } - - private def parse(batchSourceFile: BatchSourceFile, code: Array[Char]): Tree = { - try { - val parser = new syntaxAnalyzer.SourceFileParser(new ScriptSourceFile(batchSourceFile, code, 0)) - val tree = parser.templateStatSeq(false)._2 - parser.makePackaging(0, parser.atPos(0, 0, 0)(Ident(nme.EMPTY_PACKAGE_NAME)), tree) - } catch { - case _: Throwable => { - val unit = new CompilationUnit(batchSourceFile) - val unitParser = new syntaxAnalyzer.UnitParser(unit) { - override def showSyntaxErrors() {} - } - unitParser.smartParse() - } - } - } -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.compiler + +import scala.reflect.internal.util.{ScriptSourceFile, BatchSourceFile} +import scala.reflect.io.AbstractFile + +/** + * This class is a wrapper for accessing the parser of the Scala compiler + * from Java in a more convenient way. + * + * @author Felix Müller + * @since 0.1 + */ +class Parser { + + import Compiler._ + + def parse(code: String): Tree = { + val batchSourceFile = new BatchSourceFile("", code.toCharArray) + parse(batchSourceFile, code.toCharArray) + } + + def parseFile(path: String): Tree = { + val batchSourceFile = new BatchSourceFile(AbstractFile.getFile(path)) + parse(batchSourceFile, batchSourceFile.content.array) + } + + private def parse(batchSourceFile: BatchSourceFile, code: Array[Char]): Tree = { + try { + val parser = new syntaxAnalyzer.SourceFileParser(new ScriptSourceFile(batchSourceFile, code, 0)) + val tree = parser.templateStatSeq(false)._2 + parser.makePackaging(0, parser.atPos(0, 0, 0)(Ident(nme.EMPTY_PACKAGE_NAME)), tree) + } catch { + case _: Throwable => { + val unit = new CompilationUnit(batchSourceFile) + val unitParser = new syntaxAnalyzer.UnitParser(unit) { + override def showSyntaxErrors() {} + } + unitParser.smartParse() + } + } + } +} diff --git a/src/main/scala/org/sonar/plugins/scala/compiler/Token.scala b/src/main/scala/org/sonar/plugins/scala/compiler/Token.scala index 098957f..baf8cd5 100644 --- a/src/main/scala/org/sonar/plugins/scala/compiler/Token.scala +++ b/src/main/scala/org/sonar/plugins/scala/compiler/Token.scala @@ -1,27 +1,27 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.compiler - -/** - * Represent a token. Lines must start at 1. - * - * @since 0.1 - */ -case class Token(tokenType: Int, line: Int) +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.compiler + +/** + * Represent a token. Lines must start at 1. + * + * @since 0.1 + */ +case class Token(tokenType: Int, line: Int) diff --git a/src/main/scala/org/sonar/plugins/scala/language/CodeDetector.scala b/src/main/scala/org/sonar/plugins/scala/language/CodeDetector.scala index f4b26fe..f99fae7 100644 --- a/src/main/scala/org/sonar/plugins/scala/language/CodeDetector.scala +++ b/src/main/scala/org/sonar/plugins/scala/language/CodeDetector.scala @@ -1,66 +1,66 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language - -import org.sonar.plugins.scala.compiler.{ Compiler, Parser } - -/** - * This object is a helper object for detecting valid Scala code - * in a given piece of source code. - * - * @author Felix Müller - * @since 0.1 - */ -object CodeDetector { - - import Compiler._ - - private lazy val parser = new Parser() - - def hasDetectedCode(code: String) = { - - def lookingForSyntaxTreesWithCode(tree: Tree) : Boolean = tree match { - - case PackageDef(identifier: RefTree, content) => - if (!identifier.name.equals(nme.EMPTY_PACKAGE_NAME)) { - true - } else { - content.exists(lookingForSyntaxTreesWithCode) - } - - case Apply(function, args) => - args.exists(lookingForSyntaxTreesWithCode) - - case ClassDef(_, _, _, _) - | ModuleDef(_, _, _) - | ValDef(_, _, _, _) - | DefDef(_, _, _, _, _, _) - | Function(_ , _) - | Assign(_, _) - | LabelDef(_, _, _) => - true - - case _ => - false - } - - lookingForSyntaxTreesWithCode(parser.parse(code)) - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language + +import org.sonar.plugins.scala.compiler.{ Compiler, Parser } + +/** + * This object is a helper object for detecting valid Scala code + * in a given piece of source code. + * + * @author Felix Müller + * @since 0.1 + */ +object CodeDetector { + + import Compiler._ + + private lazy val parser = new Parser() + + def hasDetectedCode(code: String) = { + + def lookingForSyntaxTreesWithCode(tree: Tree) : Boolean = tree match { + + case PackageDef(identifier: RefTree, content) => + if (!identifier.name.equals(nme.EMPTY_PACKAGE_NAME)) { + true + } else { + content.exists(lookingForSyntaxTreesWithCode) + } + + case Apply(function, args) => + args.exists(lookingForSyntaxTreesWithCode) + + case ClassDef(_, _, _, _) + | ModuleDef(_, _, _) + | ValDef(_, _, _, _) + | DefDef(_, _, _, _, _, _) + | Function(_ , _) + | Assign(_, _) + | LabelDef(_, _, _) => + true + + case _ => + false + } + + lookingForSyntaxTreesWithCode(parser.parse(code)) + } } \ No newline at end of file diff --git a/src/main/scala/org/sonar/plugins/scala/language/PackageResolver.scala b/src/main/scala/org/sonar/plugins/scala/language/PackageResolver.scala index 3767493..fc7b5e5 100644 --- a/src/main/scala/org/sonar/plugins/scala/language/PackageResolver.scala +++ b/src/main/scala/org/sonar/plugins/scala/language/PackageResolver.scala @@ -1,76 +1,76 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language - -import org.sonar.plugins.scala.compiler.{ Compiler, Parser } - -/** - * This object is a helper object for resolving the package name of - * a given Scala file. - * - * @author Felix Müller - * @since 0.1 - */ -object PackageResolver { - - import Compiler._ - - private lazy val parser = new Parser() - - /** - * This function resolves the upper package name of a given file. - * - * @param path the path of the given file - * @return the upper package name - */ - def resolvePackageNameOfFile(path: String) : String = { - - def traversePackageDefs(tree: Tree) : Seq[String] = tree match { - - case PackageDef(Ident(name), List(p: PackageDef)) => - List(name.toString()) ++ traversePackageDefs(p) - - case PackageDef(s: Select, List(p: PackageDef)) => - traversePackageDefs(s) ++ traversePackageDefs(p) - - case PackageDef(Ident(name), _) => - List(name.toString()) - - case PackageDef(s: Select, _) => - traversePackageDefs(s) - - case Select(Ident(identName), name) => - List(identName.toString(), name.toString()) - - case Select(qualifiers, name) => - traversePackageDefs(qualifiers) ++ List(name.toString()) - - case _ => - Nil - } - - val packageName = traversePackageDefs(parser.parseFile(path)).foldLeft("")(_ + "." + _) - if (packageName.length() > 0) { - packageName.substring(1) - } else { - packageName - } - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language + +import org.sonar.plugins.scala.compiler.{ Compiler, Parser } + +/** + * This object is a helper object for resolving the package name of + * a given Scala file. + * + * @author Felix Müller + * @since 0.1 + */ +object PackageResolver { + + import Compiler._ + + private lazy val parser = new Parser() + + /** + * This function resolves the upper package name of a given file. + * + * @param path the path of the given file + * @return the upper package name + */ + def resolvePackageNameOfFile(path: String) : String = { + + def traversePackageDefs(tree: Tree) : Seq[String] = tree match { + + case PackageDef(Ident(name), List(p: PackageDef)) => + List(name.toString()) ++ traversePackageDefs(p) + + case PackageDef(s: Select, List(p: PackageDef)) => + traversePackageDefs(s) ++ traversePackageDefs(p) + + case PackageDef(Ident(name), _) => + List(name.toString()) + + case PackageDef(s: Select, _) => + traversePackageDefs(s) + + case Select(Ident(identName), name) => + List(identName.toString(), name.toString()) + + case Select(qualifiers, name) => + traversePackageDefs(qualifiers) ++ List(name.toString()) + + case _ => + Nil + } + + val packageName = traversePackageDefs(parser.parseFile(path)).foldLeft("")(_ + "." + _) + if (packageName.length() > 0) { + packageName.substring(1) + } else { + packageName + } + } } \ No newline at end of file diff --git a/src/main/scala/org/sonar/plugins/scala/metrics/FunctionCounter.scala b/src/main/scala/org/sonar/plugins/scala/metrics/FunctionCounter.scala index eb0feb9..c2be64f 100644 --- a/src/main/scala/org/sonar/plugins/scala/metrics/FunctionCounter.scala +++ b/src/main/scala/org/sonar/plugins/scala/metrics/FunctionCounter.scala @@ -1,108 +1,108 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics - -import org.sonar.plugins.scala.compiler.{ Compiler, Parser } - -/** - * This object is a helper object for counting all functions - * in a given Scala source. - * - * @author Felix Müller - * @since 0.1 - */ -object FunctionCounter { - - import Compiler._ - - private lazy val parser = new Parser() - - // TODO improve counting functions - def countFunctions(source: String) = { - - def countFunctionTrees(tree: Tree, foundFunctions: Int = 0) : Int = tree match { - - // recursive descent until found a syntax tree with countable functions - case PackageDef(_, content) => - foundFunctions + onList(content, countFunctionTrees(_, 0)) - - case Template(_, _, content) => - foundFunctions + onList(content, countFunctionTrees(_, 0)) - - case ClassDef(_, _, _, content) => - countFunctionTrees(content, foundFunctions) - - case ModuleDef(_, _, content) => - countFunctionTrees(content, foundFunctions) - - case DocDef(_, content) => - countFunctionTrees(content, foundFunctions) - - case ValDef(_, _, _, content) => - countFunctionTrees(content, foundFunctions) - - case Block(stats, expr) => - foundFunctions + onList(stats, countFunctionTrees(_, 0)) + countFunctionTrees(expr) - - case Apply(_, args) => - foundFunctions + onList(args, countFunctionTrees(_, 0)) - - case Assign(_, rhs) => - countFunctionTrees(rhs, foundFunctions) - - case LabelDef(_, _, rhs) => - countFunctionTrees(rhs, foundFunctions) - - case If(cond, thenBlock, elseBlock) => - foundFunctions + countFunctionTrees(cond) + countFunctionTrees(thenBlock) + countFunctionTrees(elseBlock) - - case Match(selector, cases) => - foundFunctions + countFunctionTrees(selector) + onList(cases, countFunctionTrees(_, 0)) - - case CaseDef(pat, guard, body) => - foundFunctions + countFunctionTrees(pat) + countFunctionTrees(guard) + countFunctionTrees(body) - - case Try(block, catches, finalizer) => - foundFunctions + countFunctionTrees(block) + onList(catches, countFunctionTrees(_, 0)) - - case Throw(expr) => - countFunctionTrees(expr, foundFunctions) - - case Function(_, body) => - countFunctionTrees(body, foundFunctions) - - /* - * Countable function declarations are functions and methods. - */ - - case defDef: DefDef => - if (isEmptyConstructor(defDef)) { - countFunctionTrees(defDef.rhs, foundFunctions) - } else { - countFunctionTrees(defDef.rhs, foundFunctions + 1) - } - - case _ => - foundFunctions - } - - countFunctionTrees(parser.parse(source)) - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics + +import org.sonar.plugins.scala.compiler.{ Compiler, Parser } + +/** + * This object is a helper object for counting all functions + * in a given Scala source. + * + * @author Felix Müller + * @since 0.1 + */ +object FunctionCounter { + + import Compiler._ + + private lazy val parser = new Parser() + + // TODO improve counting functions + def countFunctions(source: String) = { + + def countFunctionTrees(tree: Tree, foundFunctions: Int = 0) : Int = tree match { + + // recursive descent until found a syntax tree with countable functions + case PackageDef(_, content) => + foundFunctions + onList(content, countFunctionTrees(_, 0)) + + case Template(_, _, content) => + foundFunctions + onList(content, countFunctionTrees(_, 0)) + + case ClassDef(_, _, _, content) => + countFunctionTrees(content, foundFunctions) + + case ModuleDef(_, _, content) => + countFunctionTrees(content, foundFunctions) + + case DocDef(_, content) => + countFunctionTrees(content, foundFunctions) + + case ValDef(_, _, _, content) => + countFunctionTrees(content, foundFunctions) + + case Block(stats, expr) => + foundFunctions + onList(stats, countFunctionTrees(_, 0)) + countFunctionTrees(expr) + + case Apply(_, args) => + foundFunctions + onList(args, countFunctionTrees(_, 0)) + + case Assign(_, rhs) => + countFunctionTrees(rhs, foundFunctions) + + case LabelDef(_, _, rhs) => + countFunctionTrees(rhs, foundFunctions) + + case If(cond, thenBlock, elseBlock) => + foundFunctions + countFunctionTrees(cond) + countFunctionTrees(thenBlock) + countFunctionTrees(elseBlock) + + case Match(selector, cases) => + foundFunctions + countFunctionTrees(selector) + onList(cases, countFunctionTrees(_, 0)) + + case CaseDef(pat, guard, body) => + foundFunctions + countFunctionTrees(pat) + countFunctionTrees(guard) + countFunctionTrees(body) + + case Try(block, catches, finalizer) => + foundFunctions + countFunctionTrees(block) + onList(catches, countFunctionTrees(_, 0)) + + case Throw(expr) => + countFunctionTrees(expr, foundFunctions) + + case Function(_, body) => + countFunctionTrees(body, foundFunctions) + + /* + * Countable function declarations are functions and methods. + */ + + case defDef: DefDef => + if (isEmptyConstructor(defDef)) { + countFunctionTrees(defDef.rhs, foundFunctions) + } else { + countFunctionTrees(defDef.rhs, foundFunctions + 1) + } + + case _ => + foundFunctions + } + + countFunctionTrees(parser.parse(source)) + } } \ No newline at end of file diff --git a/src/main/scala/org/sonar/plugins/scala/metrics/StatementCounter.scala b/src/main/scala/org/sonar/plugins/scala/metrics/StatementCounter.scala index 1da05c4..095f4a3 100644 --- a/src/main/scala/org/sonar/plugins/scala/metrics/StatementCounter.scala +++ b/src/main/scala/org/sonar/plugins/scala/metrics/StatementCounter.scala @@ -1,114 +1,114 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics - -/** - * This object is a helper object for counting all statements - * in a given Scala source. - * - * @author Felix Müller - * @since 0.1 - */ -object StatementCounter { - - import scalariform.parser._ - - def countStatements(source: String) = { - - def countStatementTreesOnList(trees: List[AstNode]) : Int = { - trees.map(countStatementTrees(_)).foldLeft(0)(_ + _) - } - - def countStatementsOfDefOrDcl(body: AstNode) : Int = { - val bodyStatementCount = countStatementTrees(body) - if (bodyStatementCount == 0) { - 1 - } else { - bodyStatementCount - } - } - - def countStatementTrees(tree: AstNode, foundStatements: Int = 0) : Int = tree match { - - case AnonymousFunction(_, _, body) => - foundStatements + countStatementTrees(body) - - case FunDefOrDcl(_, _, _, _, _, funBodyOption, _) => - funBodyOption match { - case Some(funBody) => - foundStatements + countStatementsOfDefOrDcl(funBody) - case _ => - foundStatements - } - - case PatDefOrDcl(_, _, _, _, equalsClauseOption) => - equalsClauseOption match { - case Some(equalsClause) => - foundStatements + countStatementsOfDefOrDcl(equalsClause._2) - case _ => - foundStatements - } - - case ForExpr(_, _, _, _, _, yieldOption, body) => - val bodyStatementCount = countStatementTrees(body) - yieldOption match { - case Some(_) => - if (bodyStatementCount == 0) { - foundStatements + 2 - } else { - foundStatements + bodyStatementCount + 1 - } - - case _ => - foundStatements + bodyStatementCount + 1 - } - - case IfExpr(_, _, _, body, elseClauseOption) => - elseClauseOption match { - case Some(elseClause) => - foundStatements + 1 + countStatementTrees(body) + countStatementTrees(elseClause) - case _ => - foundStatements + 1 + countStatementTrees(body) - } - - case ElseClause(_, _, elseBody) => - countStatementTrees(elseBody, foundStatements + 1) - - case CallExpr(exprDotOpt, _, _, newLineOptsAndArgumentExpr, _) => - val bodyStatementCount = countStatementTreesOnList(newLineOptsAndArgumentExpr.map(_._2)) - if (bodyStatementCount > 1) { - foundStatements + 1 + bodyStatementCount - } else { - foundStatements + 1 - } - - case InfixExpr(_, _, _, _) | PostfixExpr(_, _) => - foundStatements + 1 - - case _ => - foundStatements + countStatementTreesOnList(tree.immediateChildren) - } - - ScalaParser.parse(source) match { - case Some(ast) => countStatementTrees(ast) - case _ => 0 - } - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics + +/** + * This object is a helper object for counting all statements + * in a given Scala source. + * + * @author Felix Müller + * @since 0.1 + */ +object StatementCounter { + + import scalariform.parser._ + + def countStatements(source: String) = { + + def countStatementTreesOnList(trees: List[AstNode]) : Int = { + trees.map(countStatementTrees(_)).foldLeft(0)(_ + _) + } + + def countStatementsOfDefOrDcl(body: AstNode) : Int = { + val bodyStatementCount = countStatementTrees(body) + if (bodyStatementCount == 0) { + 1 + } else { + bodyStatementCount + } + } + + def countStatementTrees(tree: AstNode, foundStatements: Int = 0) : Int = tree match { + + case AnonymousFunction(_, _, body) => + foundStatements + countStatementTrees(body) + + case FunDefOrDcl(_, _, _, _, _, funBodyOption, _) => + funBodyOption match { + case Some(funBody) => + foundStatements + countStatementsOfDefOrDcl(funBody) + case _ => + foundStatements + } + + case PatDefOrDcl(_, _, _, _, equalsClauseOption) => + equalsClauseOption match { + case Some(equalsClause) => + foundStatements + countStatementsOfDefOrDcl(equalsClause._2) + case _ => + foundStatements + } + + case ForExpr(_, _, _, _, _, yieldOption, body) => + val bodyStatementCount = countStatementTrees(body) + yieldOption match { + case Some(_) => + if (bodyStatementCount == 0) { + foundStatements + 2 + } else { + foundStatements + bodyStatementCount + 1 + } + + case _ => + foundStatements + bodyStatementCount + 1 + } + + case IfExpr(_, _, _, body, elseClauseOption) => + elseClauseOption match { + case Some(elseClause) => + foundStatements + 1 + countStatementTrees(body) + countStatementTrees(elseClause) + case _ => + foundStatements + 1 + countStatementTrees(body) + } + + case ElseClause(_, _, elseBody) => + countStatementTrees(elseBody, foundStatements + 1) + + case CallExpr(exprDotOpt, _, _, newLineOptsAndArgumentExpr, _) => + val bodyStatementCount = countStatementTreesOnList(newLineOptsAndArgumentExpr.map(_._2)) + if (bodyStatementCount > 1) { + foundStatements + 1 + bodyStatementCount + } else { + foundStatements + 1 + } + + case InfixExpr(_, _, _, _) | PostfixExpr(_, _) => + foundStatements + 1 + + case _ => + foundStatements + countStatementTreesOnList(tree.immediateChildren) + } + + ScalaParser.parse(source) match { + case Some(ast) => countStatementTrees(ast) + case _ => 0 + } + } } \ No newline at end of file diff --git a/src/main/scala/org/sonar/plugins/scala/metrics/TypeCounter.scala b/src/main/scala/org/sonar/plugins/scala/metrics/TypeCounter.scala index db05757..53f2617 100644 --- a/src/main/scala/org/sonar/plugins/scala/metrics/TypeCounter.scala +++ b/src/main/scala/org/sonar/plugins/scala/metrics/TypeCounter.scala @@ -1,96 +1,96 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics - -import org.sonar.plugins.scala.compiler.{ Compiler, Parser } - -/** - * This object is a helper object for counting all types - * in a given Scala source. - * - * @author Felix Müller - * @since 0.1 - */ -object TypeCounter { - - import Compiler._ - - private lazy val parser = new Parser() - - def countTypes(source: String) = { - - def countTypeTrees(tree: Tree, foundTypes: Int = 0) : Int = tree match { - - // recursive descent until found a syntax tree with countable type declaration - case PackageDef(_, content) => - foundTypes + onList(content, countTypeTrees(_, 0)) - - case Template(_, _, content) => - foundTypes + onList(content, countTypeTrees(_, 0)) - - case DocDef(_, content) => - countTypeTrees(content, foundTypes) - - case CaseDef(pat, guard, body) => - foundTypes + countTypeTrees(pat) + countTypeTrees(guard) + countTypeTrees(body) - - case DefDef(_, _, _, _, _, content) => - countTypeTrees(content, foundTypes) - - case ValDef(_, _, _, content) => - countTypeTrees(content, foundTypes) - - case Assign(_, rhs) => - countTypeTrees(rhs, foundTypes) - - case LabelDef(_, _, rhs) => - countTypeTrees(rhs, foundTypes) - - case If(cond, thenBlock, elseBlock) => - foundTypes + countTypeTrees(cond) + countTypeTrees(thenBlock) + countTypeTrees(elseBlock) - - case Block(stats, expr) => - foundTypes + onList(stats, countTypeTrees(_, 0)) + countTypeTrees(expr) - - case Match(selector, cases) => - foundTypes + countTypeTrees(selector) + onList(cases, countTypeTrees(_, 0)) - - case Try(block, catches, finalizer) => - foundTypes + countTypeTrees(block) + onList(catches, countTypeTrees(_, 0)) + countTypeTrees(finalizer) - - /* - * Countable type declarations are classes, traits and objects. - * ClassDef represents classes and traits. - * ModuleDef is the syntax tree for object declarations. - */ - - case ClassDef(_, _, _, content) => - countTypeTrees(content, foundTypes + 1) - - case ModuleDef(_, _, content) => - countTypeTrees(content, foundTypes + 1) - - case _ => - foundTypes - } - - countTypeTrees(parser.parse(source)) - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics + +import org.sonar.plugins.scala.compiler.{ Compiler, Parser } + +/** + * This object is a helper object for counting all types + * in a given Scala source. + * + * @author Felix Müller + * @since 0.1 + */ +object TypeCounter { + + import Compiler._ + + private lazy val parser = new Parser() + + def countTypes(source: String) = { + + def countTypeTrees(tree: Tree, foundTypes: Int = 0) : Int = tree match { + + // recursive descent until found a syntax tree with countable type declaration + case PackageDef(_, content) => + foundTypes + onList(content, countTypeTrees(_, 0)) + + case Template(_, _, content) => + foundTypes + onList(content, countTypeTrees(_, 0)) + + case DocDef(_, content) => + countTypeTrees(content, foundTypes) + + case CaseDef(pat, guard, body) => + foundTypes + countTypeTrees(pat) + countTypeTrees(guard) + countTypeTrees(body) + + case DefDef(_, _, _, _, _, content) => + countTypeTrees(content, foundTypes) + + case ValDef(_, _, _, content) => + countTypeTrees(content, foundTypes) + + case Assign(_, rhs) => + countTypeTrees(rhs, foundTypes) + + case LabelDef(_, _, rhs) => + countTypeTrees(rhs, foundTypes) + + case If(cond, thenBlock, elseBlock) => + foundTypes + countTypeTrees(cond) + countTypeTrees(thenBlock) + countTypeTrees(elseBlock) + + case Block(stats, expr) => + foundTypes + onList(stats, countTypeTrees(_, 0)) + countTypeTrees(expr) + + case Match(selector, cases) => + foundTypes + countTypeTrees(selector) + onList(cases, countTypeTrees(_, 0)) + + case Try(block, catches, finalizer) => + foundTypes + countTypeTrees(block) + onList(catches, countTypeTrees(_, 0)) + countTypeTrees(finalizer) + + /* + * Countable type declarations are classes, traits and objects. + * ClassDef represents classes and traits. + * ModuleDef is the syntax tree for object declarations. + */ + + case ClassDef(_, _, _, content) => + countTypeTrees(content, foundTypes + 1) + + case ModuleDef(_, _, content) => + countTypeTrees(content, foundTypes + 1) + + case _ => + foundTypes + } + + countTypeTrees(parser.parse(source)) + } } \ No newline at end of file diff --git a/src/main/scala/org/sonar/plugins/scala/metrics/package.scala b/src/main/scala/org/sonar/plugins/scala/metrics/package.scala index 4d8d6f6..afed61c 100644 --- a/src/main/scala/org/sonar/plugins/scala/metrics/package.scala +++ b/src/main/scala/org/sonar/plugins/scala/metrics/package.scala @@ -1,66 +1,66 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala - -package object metrics { - - import org.sonar.plugins.scala.compiler.Compiler._ - - def isEmptyBlock(block: Tree) = block match { - case literal: Literal => - val isEmptyConstant = literal.value match { - case Constant(value) => value.toString().equals("()") - case _ => false - } - literal.isEmpty || isEmptyConstant - - case _ => block.isEmpty - } - - def isEmptyConstructor(constructor: DefDef) = { - if (constructor.name.startsWith(nme.CONSTRUCTOR) || - constructor.name.startsWith(nme.MIXIN_CONSTRUCTOR)) { - - constructor.rhs match { - - case Block(stats, expr) => - if (stats.size == 0) { - true - } else { - stats.size == 1 && - (stats(0).toString().startsWith("super." + nme.CONSTRUCTOR) || - stats(0).toString().startsWith("super." + nme.MIXIN_CONSTRUCTOR)) && - isEmptyBlock(expr) - } - - case _ => - constructor.isEmpty - } - } else { - false - } - } - - /** - * Helper function which applies a function on every AST in a given list and - * sums up the results. - */ - def onList(trees: List[Tree], treeFunction: Tree => Int) = trees.map(treeFunction).sum -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala + +package object metrics { + + import org.sonar.plugins.scala.compiler.Compiler._ + + def isEmptyBlock(block: Tree) = block match { + case literal: Literal => + val isEmptyConstant = literal.value match { + case Constant(value) => value.toString().equals("()") + case _ => false + } + literal.isEmpty || isEmptyConstant + + case _ => block.isEmpty + } + + def isEmptyConstructor(constructor: DefDef) = { + if (constructor.name.startsWith(nme.CONSTRUCTOR) || + constructor.name.startsWith(nme.MIXIN_CONSTRUCTOR)) { + + constructor.rhs match { + + case Block(stats, expr) => + if (stats.size == 0) { + true + } else { + stats.size == 1 && + (stats(0).toString().startsWith("super." + nme.CONSTRUCTOR) || + stats(0).toString().startsWith("super." + nme.MIXIN_CONSTRUCTOR)) && + isEmptyBlock(expr) + } + + case _ => + constructor.isEmpty + } + } else { + false + } + } + + /** + * Helper function which applies a function on every AST in a given list and + * sums up the results. + */ + def onList(trees: List[Tree], treeFunction: Tree => Int) = trees.map(treeFunction).sum +} diff --git a/src/main/scala/org/sonar/plugins/scala/util/MetricDistribution.scala b/src/main/scala/org/sonar/plugins/scala/util/MetricDistribution.scala index 8f9710d..365a5a2 100644 --- a/src/main/scala/org/sonar/plugins/scala/util/MetricDistribution.scala +++ b/src/main/scala/org/sonar/plugins/scala/util/MetricDistribution.scala @@ -1,48 +1,48 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.util - -import collection.immutable.TreeMap - -import org.sonar.api.measures.{ Metric, RangeDistributionBuilder } - -class MetricDistribution(metric: Metric[String], ranges: Array[Number]) { - - var distribution = TreeMap[Double, Int]() - - def add(value: Double) { - add(value, 1) - } - - def add(value: Double, count: Int) { - val oldValue = distribution.getOrElse(value, 0) - distribution = distribution.updated(value, oldValue + count) - } - - def add(metricDistribution: MetricDistribution) { - metricDistribution.distribution.foreach(entry => add(entry._1, entry._2)) - } - - def getMeasure() = { - val rangeDistribution = new RangeDistributionBuilder(metric, ranges) - distribution.foreach(entry => rangeDistribution.add(entry._1, entry._2)) - rangeDistribution.build - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.util + +import collection.immutable.TreeMap + +import org.sonar.api.measures.{ Metric, RangeDistributionBuilder } + +class MetricDistribution(metric: Metric[String], ranges: Array[Number]) { + + var distribution = TreeMap[Double, Int]() + + def add(value: Double) { + add(value, 1) + } + + def add(value: Double, count: Int) { + val oldValue = distribution.getOrElse(value, 0) + distribution = distribution.updated(value, oldValue + count) + } + + def add(metricDistribution: MetricDistribution) { + metricDistribution.distribution.foreach(entry => add(entry._1, entry._2)) + } + + def getMeasure() = { + val rangeDistribution = new RangeDistributionBuilder(metric, ranges) + distribution.foreach(entry => rangeDistribution.add(entry._1, entry._2)) + rangeDistribution.build + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/cpd/ScalaTokenizerTest.java b/src/test/java/org/sonar/plugins/scala/cpd/ScalaTokenizerTest.java index f4cf756..f8ea2d9 100644 --- a/src/test/java/org/sonar/plugins/scala/cpd/ScalaTokenizerTest.java +++ b/src/test/java/org/sonar/plugins/scala/cpd/ScalaTokenizerTest.java @@ -1,110 +1,89 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.cpd; - - -public class ScalaTokenizerTest { - -// @Before -// public void init() { -// TokenEntry.clearImages(); -// } -// -// @Test -// public void noDuplications() throws IOException { -// CPD cpd = getCPD(10); -// cpd.add(resourceToFile("/cpd/NoDuplications.scala")); -// cpd.go(); -// assertThat(getMatches(cpd).size(), is(0)); -// } -// -// @Test -// public void noDuplicationsWith6Tokens() throws IOException { -// CPD cpd = getCPD(6); -// cpd.add(resourceToFile("/cpd/Duplications5Tokens.scala")); -// cpd.go(); -// assertThat(getMatches(cpd).size(), is(0)); -// } -// -// @Test -// public void duplicationWith5Tokens() throws IOException { -// CPD cpd = getCPD(5); -// cpd.add(resourceToFile("/cpd/Duplications5Tokens.scala")); -// cpd.go(); -// List matches = getMatches(cpd); -// assertThat(matches.size(), is(1)); -// assertThat(matches.get(0).getFirstMark().getBeginLine(), is(2)); -// assertThat(matches.get(0).getSecondMark().getBeginLine(), is(5)); -// } -// -// @Test -// public void newLineTokenEnables5TokenDuplication() throws IOException { -// CPD cpd = getCPD(5); -// cpd.add(resourceToFile("/cpd/NewlineToken.scala")); -// cpd.go(); -// List matches = getMatches(cpd); -// assertThat(matches.get(0).getFirstMark().getBeginLine(), is(2)); -// assertThat(matches.get(0).getSecondMark().getBeginLine(), is(3)); -// } -// -// @Test -// public void newLineAndNewLinesTokensNo5TokensDuplication() throws IOException { -// CPD cpd = getCPD(5); -// cpd.add(resourceToFile("/cpd/NewlinesToken.scala")); -// cpd.go(); -// assertThat(getMatches(cpd).size(), is(0)); -// } -// -// @Test -// public void twoDuplicatedBlocks() throws IOException { -// CPD cpd = getCPD(5); -// cpd.add(resourceToFile("/cpd/TwoDuplicatedBlocks.scala")); -// cpd.go(); -// List matches = getMatches(cpd); -// assertThat(matches.get(0).getFirstMark().getBeginLine(), is(2)); -// assertThat(matches.get(0).getSecondMark().getBeginLine(), is(7)); -// assertThat(matches.get(0).getLineCount(), is(4)); -// } -// -// private File resourceToFile(String path) { -// return FileUtils.toFile(getClass().getResource(path)); -// } -// -// private CPD getCPD(int minimumTokens) { -// AbstractLanguage language = new AbstractLanguage(new ScalaTokenizer(), "scala") { -// }; -// CPD cpd = new CPD(minimumTokens, language); -// cpd.setEncoding(Charset.defaultCharset().name()); -// cpd.setLoadSourceCodeSlices(false); -// return cpd; -// } -// -// private List getMatches(CPD cpd) { -// List matches = new ArrayList(); -// -// Iterator iterator = cpd.getMatches(); -// while (iterator.hasNext()) { -// matches.add(iterator.next()); -// } -// -// return matches; -// } - -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.cpd; + +import static org.junit.Assert.assertEquals; + + +import java.io.File; + +import net.sourceforge.pmd.cpd.SourceCode; +import net.sourceforge.pmd.cpd.TokenEntry; +import net.sourceforge.pmd.cpd.Tokenizer; +import net.sourceforge.pmd.cpd.Tokens; + +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Test; + +public class ScalaTokenizerTest { + + @Before + public void init() { + TokenEntry.clearImages(); + } + + @Test + public void test1() throws Throwable { + Tokenizer tokenizer = new ScalaTokenizer(); + SourceCode sourceCode = new SourceCode(new SourceCode.FileCodeLoader(resourceToFile("/cpd/NewlineToken.scala"), "UTF-8")); + Tokens tokens = new Tokens(); + tokenizer.tokenize(sourceCode, tokens); + + assertEquals(19, tokens.size()); + } + + @Test + public void test2() throws Throwable { + Tokenizer tokenizer = new ScalaTokenizer(); + SourceCode sourceCode = new SourceCode(new SourceCode.FileCodeLoader(resourceToFile("/cpd/NewlinesToken.scala"), "UTF-8")); + Tokens tokens = new Tokens(); + tokenizer.tokenize(sourceCode, tokens); + + assertEquals(24, tokens.size()); + } + + @Test + public void test3() throws Throwable { + Tokenizer tokenizer = new ScalaTokenizer(); + SourceCode sourceCode = new SourceCode(new SourceCode.FileCodeLoader(resourceToFile("/cpd/Empty.scala"), "UTF-8")); + Tokens tokens = new Tokens(); + tokenizer.tokenize(sourceCode, tokens); + + assertEquals(1, tokens.size()); + } + + @Test + public void test4() throws Throwable { + Tokenizer tokenizer = new ScalaTokenizer(); + SourceCode sourceCode = new SourceCode(new SourceCode.FileCodeLoader(resourceToFile("/cpd/NewlinesToken.scala"), "UTF-8")); + Tokens tokens = new Tokens(); + tokenizer.tokenize(sourceCode, tokens); + + assertEquals("class NewlinesToken {", sourceCode.getSlice(1, 1)); + assertEquals("val i = 42", sourceCode.getSlice(2, 2)); + + } + + private File resourceToFile(String path) { + return FileUtils.toFile(getClass().getResource(path)); + } + +} diff --git a/src/test/java/org/sonar/plugins/scala/language/CommentTest.java b/src/test/java/org/sonar/plugins/scala/language/CommentTest.java index 7c9f648..f6e592c 100644 --- a/src/test/java/org/sonar/plugins/scala/language/CommentTest.java +++ b/src/test/java/org/sonar/plugins/scala/language/CommentTest.java @@ -1,109 +1,109 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -import java.io.IOException; - -import org.junit.Test; - -public class CommentTest { - - @Test - public void shouldCountOneNumberOfCommentLine() throws IOException { - Comment comment = new Comment("// This is a comment", CommentType.NORMAL); - assertThat(comment.getNumberOfLines(), is(1)); - } - - @Test - public void shouldCountAllNumberOfCommentLines() throws IOException { - Comment comment = new Comment("/* This is the first comment line\r\n" - + "* second line\r\n" - + "* and this the third and last line */", - CommentType.NORMAL); - assertThat(comment.getNumberOfLines(), is(3)); - } - - @Test - public void shouldCountZeorCommentLinesIfCommentIsEmpty() throws IOException { - Comment comment = new Comment("", CommentType.NORMAL); - assertThat(comment.getNumberOfLines(), is(0)); - } - - @Test - public void shouldCountOneCommentedOutLineOfCode() throws IOException { - Comment comment = new Comment("// val a = 1", CommentType.NORMAL); - assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(1)); - } - - @Test - public void shouldCountAllCommentedOutLinesOfCode() throws IOException { - Comment comment = new Comment("/* object Hello {\r\n" - + "* val b = 1 } */", - CommentType.NORMAL); - assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(2)); - } - - @Test - public void shouldCountZeorCommentedOutLinesOfCodeIfCommentIsEmpty() throws IOException { - Comment comment = new Comment("", CommentType.NORMAL); - assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(0)); - } - - @Test - public void shouldNotCountAnyCommentedOutLinesOfCodeForDocComments() throws IOException { - Comment comment = new Comment("/** This is a doc comment with some code\r\n" - + "* package hello.world\r\n" - + "* class Test { val a = 1 } */", CommentType.DOC); - assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(0)); - } - - @Test - public void shouldCountAllBlankCommentLines() throws IOException { - Comment comment = new Comment("/*\r\n" - + "* this is a multi line comment with some blank lines\r\n" - + "* \t \t \r\n" - + "*/", CommentType.NORMAL); - assertThat(comment.getNumberOfBlankLines(), is(3)); - } - - @Test - public void shouldBeNormalComment() throws IOException { - Comment comment = new Comment("", CommentType.NORMAL); - assertThat(comment.isDocComment(), is(false)); - assertThat(comment.isHeaderComment(), is(false)); - } - - @Test - public void shouldBeDocComment() throws IOException { - Comment comment = new Comment("", CommentType.DOC); - assertThat(comment.isDocComment(), is(true)); - assertThat(comment.isHeaderComment(), is(false)); - } - - @Test - public void shouldBeHeaderComment() throws IOException { - Comment comment = new Comment("", CommentType.HEADER); - assertThat(comment.isDocComment(), is(false)); - assertThat(comment.isHeaderComment(), is(true)); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.io.IOException; + +import org.junit.Test; + +public class CommentTest { + + @Test + public void shouldCountOneNumberOfCommentLine() throws IOException { + Comment comment = new Comment("// This is a comment", CommentType.NORMAL); + assertThat(comment.getNumberOfLines(), is(1)); + } + + @Test + public void shouldCountAllNumberOfCommentLines() throws IOException { + Comment comment = new Comment("/* This is the first comment line\r\n" + + "* second line\r\n" + + "* and this the third and last line */", + CommentType.NORMAL); + assertThat(comment.getNumberOfLines(), is(3)); + } + + @Test + public void shouldCountZeorCommentLinesIfCommentIsEmpty() throws IOException { + Comment comment = new Comment("", CommentType.NORMAL); + assertThat(comment.getNumberOfLines(), is(0)); + } + + @Test + public void shouldCountOneCommentedOutLineOfCode() throws IOException { + Comment comment = new Comment("// val a = 1", CommentType.NORMAL); + assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(1)); + } + + @Test + public void shouldCountAllCommentedOutLinesOfCode() throws IOException { + Comment comment = new Comment("/* object Hello {\r\n" + + "* val b = 1 } */", + CommentType.NORMAL); + assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(2)); + } + + @Test + public void shouldCountZeorCommentedOutLinesOfCodeIfCommentIsEmpty() throws IOException { + Comment comment = new Comment("", CommentType.NORMAL); + assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(0)); + } + + @Test + public void shouldNotCountAnyCommentedOutLinesOfCodeForDocComments() throws IOException { + Comment comment = new Comment("/** This is a doc comment with some code\r\n" + + "* package hello.world\r\n" + + "* class Test { val a = 1 } */", CommentType.DOC); + assertThat(comment.getNumberOfCommentedOutLinesOfCode(), is(0)); + } + + @Test + public void shouldCountAllBlankCommentLines() throws IOException { + Comment comment = new Comment("/*\r\n" + + "* this is a multi line comment with some blank lines\r\n" + + "* \t \t \r\n" + + "*/", CommentType.NORMAL); + assertThat(comment.getNumberOfBlankLines(), is(3)); + } + + @Test + public void shouldBeNormalComment() throws IOException { + Comment comment = new Comment("", CommentType.NORMAL); + assertThat(comment.isDocComment(), is(false)); + assertThat(comment.isHeaderComment(), is(false)); + } + + @Test + public void shouldBeDocComment() throws IOException { + Comment comment = new Comment("", CommentType.DOC); + assertThat(comment.isDocComment(), is(true)); + assertThat(comment.isHeaderComment(), is(false)); + } + + @Test + public void shouldBeHeaderComment() throws IOException { + Comment comment = new Comment("", CommentType.HEADER); + assertThat(comment.isDocComment(), is(false)); + assertThat(comment.isHeaderComment(), is(true)); + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/language/ScalaTest.java b/src/test/java/org/sonar/plugins/scala/language/ScalaTest.java index 236f628..ebae744 100644 --- a/src/test/java/org/sonar/plugins/scala/language/ScalaTest.java +++ b/src/test/java/org/sonar/plugins/scala/language/ScalaTest.java @@ -1,48 +1,48 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language; - -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertThat; - -import org.junit.Test; -import org.sonar.api.config.Settings; - -public class ScalaTest { - - @Test - public void shouldHaveScalaLanguageKey() { - assertThat(new Scala(new Settings()).getKey(), equalTo("scala")); - assertThat(Scala.KEY, equalTo("scala")); - } - - @Test - public void shouldHaveScalaLanguageName() { - assertThat(new Scala(new Settings()).getName(), equalTo("Scala")); - assertThat(Scala.NAME, equalTo("Scala")); - } - - @Test - public void shouldHaveScalaFileSuffixes() { - String[] suffixes = new String[] { "scala" }; - assertArrayEquals(new Scala(new Settings()).getFileSuffixes(), suffixes); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertThat; + +import org.junit.Test; +import org.sonar.api.config.Settings; + +public class ScalaTest { + + @Test + public void shouldHaveScalaLanguageKey() { + assertThat(new Scala(new Settings()).getKey(), equalTo("scala")); + assertThat(Scala.KEY, equalTo("scala")); + } + + @Test + public void shouldHaveScalaLanguageName() { + assertThat(new Scala(new Settings()).getName(), equalTo("Scala")); + assertThat(Scala.NAME, equalTo("Scala")); + } + + @Test + public void shouldHaveScalaFileSuffixes() { + String[] suffixes = new String[] { "scala" }; + assertArrayEquals(new Scala(new Settings()).getFileSuffixes(), suffixes); + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/metrics/CommentsAnalyzerTest.java b/src/test/java/org/sonar/plugins/scala/metrics/CommentsAnalyzerTest.java index 26edc8e..d4e2efa 100644 --- a/src/test/java/org/sonar/plugins/scala/metrics/CommentsAnalyzerTest.java +++ b/src/test/java/org/sonar/plugins/scala/metrics/CommentsAnalyzerTest.java @@ -1,92 +1,92 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; -import org.sonar.plugins.scala.language.Comment; -import org.sonar.plugins.scala.language.CommentType; - -public class CommentsAnalyzerTest { - - @Test - public void shouldCountAllCommentLines() throws IOException { - List comments = Arrays.asList( - "// this a normal comment", - "/* this is a normal multiline coment\r\n* last line of this comment */", - "// also a normal comment"); - CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(asCommentList(comments, CommentType.NORMAL)); - assertThat(commentAnalyzer.countCommentLines(), is(4)); - } - - @Test - public void shouldCountAllHeaderCommentLines() throws IOException { - List comments = Arrays.asList( - "/* this is an one line header comment */", - "/* this is a normal multiline header coment\r\n* last line of this comment */", - "/* also a normal header comment */"); - CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(asCommentList(comments, CommentType.HEADER)); - assertThat(commentAnalyzer.countHeaderCommentLines(), is(4)); - } - - @Test - public void shouldCountAllCommentedOutLinesOfCode() throws IOException { - List comments = Arrays.asList( - "// val a = 12", - "/* list.foreach(println(_))\r\n* def inc(x: Int) = x + 1 */", - "// this a normal comment"); - CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(asCommentList(comments, CommentType.NORMAL)); - assertThat(commentAnalyzer.countCommentedOutLinesOfCode(), is(3)); - } - - @Test - public void shouldCountZeroCommentLinesForEmptyCommentsList() { - CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(Collections.emptyList()); - assertThat(commentAnalyzer.countCommentLines(), is(0)); - } - - @Test - public void shouldCountZeroHeaderCommentLinesForEmptyCommentsList() { - CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(Collections.emptyList()); - assertThat(commentAnalyzer.countHeaderCommentLines(), is(0)); - } - - @Test - public void shouldCountZeroCommentedOutLinesOfCodeForEmptyCommentsList() { - CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(Collections.emptyList()); - assertThat(commentAnalyzer.countCommentedOutLinesOfCode(), is(0)); - } - - private List asCommentList(List commentsContent, CommentType type) throws IOException { - List comments = new ArrayList(); - for (String comment : commentsContent) { - comments.add(new Comment(comment, type)); - } - return comments; - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.sonar.plugins.scala.language.Comment; +import org.sonar.plugins.scala.language.CommentType; + +public class CommentsAnalyzerTest { + + @Test + public void shouldCountAllCommentLines() throws IOException { + List comments = Arrays.asList( + "// this a normal comment", + "/* this is a normal multiline coment\r\n* last line of this comment */", + "// also a normal comment"); + CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(asCommentList(comments, CommentType.NORMAL)); + assertThat(commentAnalyzer.countCommentLines(), is(4)); + } + + @Test + public void shouldCountAllHeaderCommentLines() throws IOException { + List comments = Arrays.asList( + "/* this is an one line header comment */", + "/* this is a normal multiline header coment\r\n* last line of this comment */", + "/* also a normal header comment */"); + CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(asCommentList(comments, CommentType.HEADER)); + assertThat(commentAnalyzer.countHeaderCommentLines(), is(4)); + } + + @Test + public void shouldCountAllCommentedOutLinesOfCode() throws IOException { + List comments = Arrays.asList( + "// val a = 12", + "/* list.foreach(println(_))\r\n* def inc(x: Int) = x + 1 */", + "// this a normal comment"); + CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(asCommentList(comments, CommentType.NORMAL)); + assertThat(commentAnalyzer.countCommentedOutLinesOfCode(), is(3)); + } + + @Test + public void shouldCountZeroCommentLinesForEmptyCommentsList() { + CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(Collections.emptyList()); + assertThat(commentAnalyzer.countCommentLines(), is(0)); + } + + @Test + public void shouldCountZeroHeaderCommentLinesForEmptyCommentsList() { + CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(Collections.emptyList()); + assertThat(commentAnalyzer.countHeaderCommentLines(), is(0)); + } + + @Test + public void shouldCountZeroCommentedOutLinesOfCodeForEmptyCommentsList() { + CommentsAnalyzer commentAnalyzer = new CommentsAnalyzer(Collections.emptyList()); + assertThat(commentAnalyzer.countCommentedOutLinesOfCode(), is(0)); + } + + private List asCommentList(List commentsContent, CommentType type) throws IOException { + List comments = new ArrayList(); + for (String comment : commentsContent) { + comments.add(new Comment(comment, type)); + } + return comments; + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/metrics/LinesAnalyzerTest.java b/src/test/java/org/sonar/plugins/scala/metrics/LinesAnalyzerTest.java index 2871a53..9bf09f4 100644 --- a/src/test/java/org/sonar/plugins/scala/metrics/LinesAnalyzerTest.java +++ b/src/test/java/org/sonar/plugins/scala/metrics/LinesAnalyzerTest.java @@ -1,95 +1,95 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -import java.io.IOException; -import java.util.List; - -import org.junit.Test; -import org.sonar.plugins.scala.compiler.Lexer; -import org.sonar.plugins.scala.language.Comment; -import org.sonar.plugins.scala.util.StringUtils; - -public class LinesAnalyzerTest { - - @Test - public void shouldCountOneLine() throws IOException { - LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0"); - assertThat(linesAnalyzer.countLines(), is(1)); - } - - @Test - public void shouldCountAllLines() throws IOException { - LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0\r\n" - + "println(\"Hallo\")\r\n" - + "\r\n" - + "i = 2"); - assertThat(linesAnalyzer.countLines(), is(4)); - } - - @Test - public void shouldGiveZeroLinesForEmptySource() throws IOException { - LinesAnalyzer linesAnalyzer = getLinesAnalyzer(""); - assertThat(linesAnalyzer.countLines(), is(0)); - } - - @Test - public void shouldCountOneLineOfCode() throws IOException { - LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0"); - assertThat(linesAnalyzer.countLinesOfCode(), is(1)); - } - - @Test - public void shouldNotCountBlankLinesAsLinesOfCode() throws IOException { - LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0\r\n" + - "\r\n" + - " \t \r\n" + - "val b = 2"); - assertThat(linesAnalyzer.countLinesOfCode(), is(2)); - } - - @Test - public void shouldNotCountCommentLinesAsLinesOfCode() throws IOException { - LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0\r\n" + - "// this is comment...\r\n" + - "// test\r\n" + - "val b = 2"); - assertThat(linesAnalyzer.countLinesOfCode(), is(2)); - } - - @Test - public void shouldNotCountHeaderCommentLinesAsLinesOfCode() throws IOException { - LinesAnalyzer linesAnalyzer = getLinesAnalyzer("/**\r\n" + - "* this is a header comment...\r\n" + - "*/\r\n" + - "val b = 2"); - assertThat(linesAnalyzer.countLinesOfCode(), is(1)); - } - - private LinesAnalyzer getLinesAnalyzer(String source) throws IOException { - List lines = StringUtils.convertStringToListOfLines(source); - List comments = new Lexer().getComments(source); - CommentsAnalyzer commentsAnalyzer = new CommentsAnalyzer(comments); - return new LinesAnalyzer(lines, commentsAnalyzer); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.util.List; + +import org.junit.Test; +import org.sonar.plugins.scala.compiler.Lexer; +import org.sonar.plugins.scala.language.Comment; +import org.sonar.plugins.scala.util.StringUtils; + +public class LinesAnalyzerTest { + + @Test + public void shouldCountOneLine() throws IOException { + LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0"); + assertThat(linesAnalyzer.countLines(), is(1)); + } + + @Test + public void shouldCountAllLines() throws IOException { + LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0\r\n" + + "println(\"Hallo\")\r\n" + + "\r\n" + + "i = 2"); + assertThat(linesAnalyzer.countLines(), is(4)); + } + + @Test + public void shouldGiveZeroLinesForEmptySource() throws IOException { + LinesAnalyzer linesAnalyzer = getLinesAnalyzer(""); + assertThat(linesAnalyzer.countLines(), is(0)); + } + + @Test + public void shouldCountOneLineOfCode() throws IOException { + LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0"); + assertThat(linesAnalyzer.countLinesOfCode(), is(1)); + } + + @Test + public void shouldNotCountBlankLinesAsLinesOfCode() throws IOException { + LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0\r\n" + + "\r\n" + + " \t \r\n" + + "val b = 2"); + assertThat(linesAnalyzer.countLinesOfCode(), is(2)); + } + + @Test + public void shouldNotCountCommentLinesAsLinesOfCode() throws IOException { + LinesAnalyzer linesAnalyzer = getLinesAnalyzer("val i = 0\r\n" + + "// this is comment...\r\n" + + "// test\r\n" + + "val b = 2"); + assertThat(linesAnalyzer.countLinesOfCode(), is(2)); + } + + @Test + public void shouldNotCountHeaderCommentLinesAsLinesOfCode() throws IOException { + LinesAnalyzer linesAnalyzer = getLinesAnalyzer("/**\r\n" + + "* this is a header comment...\r\n" + + "*/\r\n" + + "val b = 2"); + assertThat(linesAnalyzer.countLinesOfCode(), is(1)); + } + + private LinesAnalyzer getLinesAnalyzer(String source) throws IOException { + List lines = StringUtils.convertStringToListOfLines(source); + List comments = new Lexer().getComments(source); + CommentsAnalyzer commentsAnalyzer = new CommentsAnalyzer(comments); + return new LinesAnalyzer(lines, commentsAnalyzer); + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/sensor/AbstractScalaSensorTest.java b/src/test/java/org/sonar/plugins/scala/sensor/AbstractScalaSensorTest.java index 23c8033..c7afe5a 100644 --- a/src/test/java/org/sonar/plugins/scala/sensor/AbstractScalaSensorTest.java +++ b/src/test/java/org/sonar/plugins/scala/sensor/AbstractScalaSensorTest.java @@ -1,76 +1,76 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.sensor; - -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.batch.fs.internal.DefaultFileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; -import org.sonar.plugins.scala.language.Scala; -import org.sonar.plugins.scala.util.FileTestUtils; - -public class AbstractScalaSensorTest { - - private AbstractScalaSensor abstractScalaSensor; - private Settings settings; - private DefaultFileSystem fileSystem; - - - @Before - public void setUp() { - Settings settings = new Settings(); - fileSystem = new DefaultFileSystem(); - abstractScalaSensor = new AbstractScalaSensor(new Scala(settings), fileSystem) { - - public void analyse(Project project, SensorContext context) { - // dummy implementation, never called in this test - } - }; - } - - @Test - public void shouldExecuteOnScalaProjects() { - Project scalaProject = mock(Project.class); - FileTestUtils.addInputFiles(fileSystem, FileTestUtils.getInputFiles( - "/scalaSourceImporter/", "MainFile", "scala", 1), false); - assertTrue(abstractScalaSensor.shouldExecuteOnProject(scalaProject)); - } - - @Test - public void shouldNotExecuteOnJavaProjects() { - Project javaProject = mock(Project.class); - FileTestUtils.addInputFiles(fileSystem, FileTestUtils.getInputFiles( - "/scalaSourceImporter/", "JavaMainFile", "java", 1), false); - assertFalse(abstractScalaSensor.shouldExecuteOnProject(javaProject)); - } - - @Test - public void shouldHaveScalaAsLanguage() { - assertThat(abstractScalaSensor.getScala(), equalTo(new Scala(settings))); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.sensor; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.config.Settings; +import org.sonar.api.resources.Project; +import org.sonar.plugins.scala.language.Scala; +import org.sonar.plugins.scala.util.FileTestUtils; + +public class AbstractScalaSensorTest { + + private AbstractScalaSensor abstractScalaSensor; + private Settings settings; + private DefaultFileSystem fileSystem; + + + @Before + public void setUp() { + Settings settings = new Settings(); + fileSystem = new DefaultFileSystem(); + abstractScalaSensor = new AbstractScalaSensor(new Scala(settings), fileSystem) { + + public void analyse(Project project, SensorContext context) { + // dummy implementation, never called in this test + } + }; + } + + @Test + public void shouldExecuteOnScalaProjects() { + Project scalaProject = mock(Project.class); + FileTestUtils.addInputFiles(fileSystem, FileTestUtils.getInputFiles( + "/scalaSourceImporter/", "MainFile", "scala", 1), false); + assertTrue(abstractScalaSensor.shouldExecuteOnProject(scalaProject)); + } + + @Test + public void shouldNotExecuteOnJavaProjects() { + Project javaProject = mock(Project.class); + FileTestUtils.addInputFiles(fileSystem, FileTestUtils.getInputFiles( + "/scalaSourceImporter/", "JavaMainFile", "java", 1), false); + assertFalse(abstractScalaSensor.shouldExecuteOnProject(javaProject)); + } + + @Test + public void shouldHaveScalaAsLanguage() { + assertThat(abstractScalaSensor.getScala(), equalTo(new Scala(settings))); + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/sensor/BaseMetricsSensorTest.java b/src/test/java/org/sonar/plugins/scala/sensor/BaseMetricsSensorTest.java index 7c9c6bd..34d08fa 100644 --- a/src/test/java/org/sonar/plugins/scala/sensor/BaseMetricsSensorTest.java +++ b/src/test/java/org/sonar/plugins/scala/sensor/BaseMetricsSensorTest.java @@ -1,183 +1,183 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.sensor; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import java.io.IOException; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.batch.fs.internal.DefaultFileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.plugins.scala.language.Scala; -import org.sonar.plugins.scala.util.FileTestUtils; - -public class BaseMetricsSensorTest { - - private static final int NUMBER_OF_FILES = 3; - - private BaseMetricsSensor baseMetricsSensor; - - private DefaultFileSystem fileSystem; - private Project project; - private SensorContext sensorContext; - private Settings settings; - - - @Before - public void setUp() { - this.settings = new Settings(); - this.fileSystem = new DefaultFileSystem(); - this.baseMetricsSensor = new BaseMetricsSensor(new Scala(settings), fileSystem); - - this.project = mock(Project.class); - this.sensorContext = mock(SensorContext.class); - } - - @Test - public void shouldIncrementFileMetricForOneScalaFile() { - analyseOneScalaFile(); - verifyMeasuring(CoreMetrics.FILES, 1.0); - } - - @Test - public void shouldIncreaseFileMetricForAllScalaFiles() throws IOException { - analyseAllScalaFiles(); - verifyMeasuring(CoreMetrics.FILES, NUMBER_OF_FILES, 1.0); - } - - @Test - public void shouldMeasureNothingWhenNoFiles() { - analyseScalaFiles(0); - verifyNoMoreInteractions(sensorContext); - } - - @Test - public void shouldMeasureFunctionComplexityDistributionForOneScalaFileOnlyOnce() { - analyseOneScalaFile(); - verify(sensorContext).saveMeasure(eq(new Measure(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION))); - } - - @Test - public void shouldMeasureFunctionComplexityDistributionForAllScalaFilesOnlyOnce() { - analyseAllScalaFiles(); - verify(sensorContext).saveMeasure(eq(new Measure(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION))); - } - - @Test - public void shouldMeasureLineMetricsForOneScalaFile() { - analyseOneScalaFile(); - verifyMeasuring(CoreMetrics.LINES); - verifyMeasuring(CoreMetrics.NCLOC); - } - - @Test - public void shouldMeasureLineMetricsForAllScalaFiles() { - analyseAllScalaFiles(); - verifyMeasuring(CoreMetrics.LINES, NUMBER_OF_FILES); - verifyMeasuring(CoreMetrics.NCLOC, NUMBER_OF_FILES); - } - - @Test - public void shouldMeasureCommentMetricsForOneScalaFile() { - analyseOneScalaFile(); - verifyMeasuring(CoreMetrics.COMMENT_LINES); - } - - @Test - public void shouldMeasureCommentMetricsForAllScalaFiles() { - analyseAllScalaFiles(); - verifyMeasuring(CoreMetrics.COMMENT_LINES, NUMBER_OF_FILES); - } - - @Test - public void shouldMeasureCodeMetricsForOneScalaFile() { - analyseOneScalaFile(); - verifyMeasuring(CoreMetrics.CLASSES); - verifyMeasuring(CoreMetrics.STATEMENTS); - verifyMeasuring(CoreMetrics.FUNCTIONS); - verifyMeasuring(CoreMetrics.COMPLEXITY); - } - - @Test - public void shouldMeasureCodeMetricsForAllScalaFiles() { - analyseAllScalaFiles(); - verifyMeasuring(CoreMetrics.CLASSES, NUMBER_OF_FILES); - verifyMeasuring(CoreMetrics.STATEMENTS, NUMBER_OF_FILES); - verifyMeasuring(CoreMetrics.FUNCTIONS, NUMBER_OF_FILES); - verifyMeasuring(CoreMetrics.COMPLEXITY, NUMBER_OF_FILES); - } - - @Test - public void shouldMeasurePublicApiMetricsForOneScalaFile() { - analyseOneScalaFile(); - verifyMeasuring(CoreMetrics.PUBLIC_API); - verifyMeasuring(CoreMetrics.PUBLIC_UNDOCUMENTED_API); - } - - @Test - public void shouldMeasurePublicApiMetricsForAllScalaFiles() { - analyseAllScalaFiles(); - verifyMeasuring(CoreMetrics.PUBLIC_API, NUMBER_OF_FILES); - verifyMeasuring(CoreMetrics.PUBLIC_UNDOCUMENTED_API, NUMBER_OF_FILES); - } - - private void verifyMeasuring(Metric metric) { - verifyMeasuring(metric, 1); - } - - private void verifyMeasuring(Metric metric, int numberOfCalls) { - verify(sensorContext, times(numberOfCalls)).saveMeasure(eq(FileTestUtils.SCALA_SOURCE_FILE), - eq(metric), any(Double.class)); - } - - private void verifyMeasuring(Metric metric, double value) { - verifyMeasuring(metric, 1, value); - } - - private void verifyMeasuring(Metric metric, int numberOfCalls, double value) { - verify(sensorContext, times(numberOfCalls)).saveMeasure(eq(FileTestUtils.SCALA_SOURCE_FILE), - eq(metric), eq(value)); - } - - private void analyseOneScalaFile() { - analyseScalaFiles(1); - } - - private void analyseAllScalaFiles() { - analyseScalaFiles(NUMBER_OF_FILES); - } - - private void analyseScalaFiles(int numberOfFiles) { - FileTestUtils.addInputFiles(fileSystem, FileTestUtils.getInputFiles("/baseMetricsSensor/", "ScalaFile", numberOfFiles), false); - baseMetricsSensor.analyse(project, sensorContext); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.sensor; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import java.io.IOException; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.config.Settings; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.plugins.scala.language.Scala; +import org.sonar.plugins.scala.util.FileTestUtils; + +public class BaseMetricsSensorTest { + + private static final int NUMBER_OF_FILES = 3; + + private BaseMetricsSensor baseMetricsSensor; + + private DefaultFileSystem fileSystem; + private Project project; + private SensorContext sensorContext; + private Settings settings; + + + @Before + public void setUp() { + this.settings = new Settings(); + this.fileSystem = new DefaultFileSystem(); + this.baseMetricsSensor = new BaseMetricsSensor(new Scala(settings), fileSystem); + + this.project = mock(Project.class); + this.sensorContext = mock(SensorContext.class); + } + + @Test + public void shouldIncrementFileMetricForOneScalaFile() { + analyseOneScalaFile(); + verifyMeasuring(CoreMetrics.FILES, 1.0); + } + + @Test + public void shouldIncreaseFileMetricForAllScalaFiles() throws IOException { + analyseAllScalaFiles(); + verifyMeasuring(CoreMetrics.FILES, NUMBER_OF_FILES, 1.0); + } + + @Test + public void shouldMeasureNothingWhenNoFiles() { + analyseScalaFiles(0); + verifyNoMoreInteractions(sensorContext); + } + + @Test + public void shouldMeasureFunctionComplexityDistributionForOneScalaFileOnlyOnce() { + analyseOneScalaFile(); + verify(sensorContext).saveMeasure(eq(new Measure(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION))); + } + + @Test + public void shouldMeasureFunctionComplexityDistributionForAllScalaFilesOnlyOnce() { + analyseAllScalaFiles(); + verify(sensorContext).saveMeasure(eq(new Measure(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION))); + } + + @Test + public void shouldMeasureLineMetricsForOneScalaFile() { + analyseOneScalaFile(); + verifyMeasuring(CoreMetrics.LINES); + verifyMeasuring(CoreMetrics.NCLOC); + } + + @Test + public void shouldMeasureLineMetricsForAllScalaFiles() { + analyseAllScalaFiles(); + verifyMeasuring(CoreMetrics.LINES, NUMBER_OF_FILES); + verifyMeasuring(CoreMetrics.NCLOC, NUMBER_OF_FILES); + } + + @Test + public void shouldMeasureCommentMetricsForOneScalaFile() { + analyseOneScalaFile(); + verifyMeasuring(CoreMetrics.COMMENT_LINES); + } + + @Test + public void shouldMeasureCommentMetricsForAllScalaFiles() { + analyseAllScalaFiles(); + verifyMeasuring(CoreMetrics.COMMENT_LINES, NUMBER_OF_FILES); + } + + @Test + public void shouldMeasureCodeMetricsForOneScalaFile() { + analyseOneScalaFile(); + verifyMeasuring(CoreMetrics.CLASSES); + verifyMeasuring(CoreMetrics.STATEMENTS); + verifyMeasuring(CoreMetrics.FUNCTIONS); + verifyMeasuring(CoreMetrics.COMPLEXITY); + } + + @Test + public void shouldMeasureCodeMetricsForAllScalaFiles() { + analyseAllScalaFiles(); + verifyMeasuring(CoreMetrics.CLASSES, NUMBER_OF_FILES); + verifyMeasuring(CoreMetrics.STATEMENTS, NUMBER_OF_FILES); + verifyMeasuring(CoreMetrics.FUNCTIONS, NUMBER_OF_FILES); + verifyMeasuring(CoreMetrics.COMPLEXITY, NUMBER_OF_FILES); + } + + @Test + public void shouldMeasurePublicApiMetricsForOneScalaFile() { + analyseOneScalaFile(); + verifyMeasuring(CoreMetrics.PUBLIC_API); + verifyMeasuring(CoreMetrics.PUBLIC_UNDOCUMENTED_API); + } + + @Test + public void shouldMeasurePublicApiMetricsForAllScalaFiles() { + analyseAllScalaFiles(); + verifyMeasuring(CoreMetrics.PUBLIC_API, NUMBER_OF_FILES); + verifyMeasuring(CoreMetrics.PUBLIC_UNDOCUMENTED_API, NUMBER_OF_FILES); + } + + private void verifyMeasuring(Metric metric) { + verifyMeasuring(metric, 1); + } + + private void verifyMeasuring(Metric metric, int numberOfCalls) { + verify(sensorContext, times(numberOfCalls)).saveMeasure(eq(FileTestUtils.SCALA_SOURCE_FILE), + eq(metric), any(Double.class)); + } + + private void verifyMeasuring(Metric metric, double value) { + verifyMeasuring(metric, 1, value); + } + + private void verifyMeasuring(Metric metric, int numberOfCalls, double value) { + verify(sensorContext, times(numberOfCalls)).saveMeasure(eq(FileTestUtils.SCALA_SOURCE_FILE), + eq(metric), eq(value)); + } + + private void analyseOneScalaFile() { + analyseScalaFiles(1); + } + + private void analyseAllScalaFiles() { + analyseScalaFiles(NUMBER_OF_FILES); + } + + private void analyseScalaFiles(int numberOfFiles) { + FileTestUtils.addInputFiles(fileSystem, FileTestUtils.getInputFiles("/baseMetricsSensor/", "ScalaFile", numberOfFiles), false); + baseMetricsSensor.analyse(project, sensorContext); + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/util/DummyScalaFile.java b/src/test/java/org/sonar/plugins/scala/util/DummyScalaFile.java index 65b039a..4a1710b 100644 --- a/src/test/java/org/sonar/plugins/scala/util/DummyScalaFile.java +++ b/src/test/java/org/sonar/plugins/scala/util/DummyScalaFile.java @@ -1,42 +1,42 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.util; - -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.plugins.scala.language.Scala; - -public class DummyScalaFile extends DefaultInputFile { - - public DummyScalaFile(boolean isUnitTest) { - super(""); - setLanguage(Scala.KEY); - setType(isUnitTest ? Type.TEST : Type.MAIN); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof InputFile)) { - return false; - } - InputFile other = (InputFile) obj; - return (language() == Scala.KEY && type() == other.type()); - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.util; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.plugins.scala.language.Scala; + +public class DummyScalaFile extends DefaultInputFile { + + public DummyScalaFile(boolean isUnitTest) { + super(""); + setLanguage(Scala.KEY); + setType(isUnitTest ? Type.TEST : Type.MAIN); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof InputFile)) { + return false; + } + InputFile other = (InputFile) obj; + return (language() == Scala.KEY && type() == other.type()); + } } \ No newline at end of file diff --git a/src/test/java/org/sonar/plugins/scala/util/FileTestUtils.java b/src/test/java/org/sonar/plugins/scala/util/FileTestUtils.java index 1680924..ff3207d 100644 --- a/src/test/java/org/sonar/plugins/scala/util/FileTestUtils.java +++ b/src/test/java/org/sonar/plugins/scala/util/FileTestUtils.java @@ -1,101 +1,101 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.util; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.fs.internal.DefaultFileSystem; -import org.sonar.api.batch.fs.internal.DefaultInputFile; - -public final class FileTestUtils { - - public static final InputFile SCALA_SOURCE_FILE = new DummyScalaFile(false); - public static final InputFile SCALA_TEST_FILE = new DummyScalaFile(true); - - private static final Logger LOGGER = LoggerFactory.getLogger(FileTestUtils.class); - - private FileTestUtils() { - // to prevent instantiation - } - - public static String getRelativePath(String path) { - return FileTestUtils.class.getResource(path).getFile(); - } - - public static List getInputFiles(String path, String fileNameBase, int numberOfFiles) { - return getInputFiles(path, fileNameBase, "scala", numberOfFiles); - } - - public static List getInputFiles(String path, String fileNameBase, String fileSuffix, int numberOfFiles) { - List mainFiles = new ArrayList(); - - URL resourceURL = FileTestUtils.class.getResource(path + fileNameBase + "1." + fileSuffix); - for (int i = 1; resourceURL != null && i <= numberOfFiles; ) { - String relativePath = path + fileNameBase + i + "." + fileSuffix; - - if (relativePath.charAt(0) == '/') { - relativePath = relativePath.substring(1); - } - - DefaultInputFile inputFile = new DefaultInputFile(relativePath); - inputFile.setLanguage(fileSuffix); - inputFile.setAbsolutePath(resourceURL.getPath()); - - mainFiles.add(inputFile); - resourceURL = FileTestUtils.class.getResource(path + fileNameBase + (++i) + "." + fileSuffix); - } - - return mainFiles; - } - - public static void addInputFiles(FileSystem fileSystem, Iterable inputFiles, boolean testFile) { - for (InputFile inputFile : inputFiles) { - ((DefaultInputFile) inputFile).setType(testFile ? InputFile.Type.TEST : InputFile.Type.MAIN); - ((DefaultFileSystem) fileSystem).add(inputFile); - } - } - - public static List getContentOfFiles(String path, String fileNameBase, int numberOfFiles) throws IOException { - List contentOfFiles = new ArrayList(); - - URL resourceURL = FileTestUtils.class.getResource(path + fileNameBase + "1.scala"); - for (int i = 1; resourceURL != null && i <= numberOfFiles; ) { - try { - contentOfFiles.add(FileUtils.readFileToString(new File(resourceURL.getFile()), Charset.defaultCharset().toString())); - } catch (IOException ioe) { - LOGGER.error("Unexpected I/O exception occurred", ioe); - throw ioe; - } - resourceURL = FileTestUtils.class.getResource(path + fileNameBase + (++i) + ".scala"); - } - - return contentOfFiles; - } -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.util; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; + +public final class FileTestUtils { + + public static final InputFile SCALA_SOURCE_FILE = new DummyScalaFile(false); + public static final InputFile SCALA_TEST_FILE = new DummyScalaFile(true); + + private static final Logger LOGGER = LoggerFactory.getLogger(FileTestUtils.class); + + private FileTestUtils() { + // to prevent instantiation + } + + public static String getRelativePath(String path) { + return FileTestUtils.class.getResource(path).getFile(); + } + + public static List getInputFiles(String path, String fileNameBase, int numberOfFiles) { + return getInputFiles(path, fileNameBase, "scala", numberOfFiles); + } + + public static List getInputFiles(String path, String fileNameBase, String fileSuffix, int numberOfFiles) { + List mainFiles = new ArrayList(); + + URL resourceURL = FileTestUtils.class.getResource(path + fileNameBase + "1." + fileSuffix); + for (int i = 1; resourceURL != null && i <= numberOfFiles; ) { + String relativePath = path + fileNameBase + i + "." + fileSuffix; + + if (relativePath.charAt(0) == '/') { + relativePath = relativePath.substring(1); + } + + DefaultInputFile inputFile = new DefaultInputFile(relativePath); + inputFile.setLanguage(fileSuffix); + inputFile.setAbsolutePath(resourceURL.getPath()); + + mainFiles.add(inputFile); + resourceURL = FileTestUtils.class.getResource(path + fileNameBase + (++i) + "." + fileSuffix); + } + + return mainFiles; + } + + public static void addInputFiles(FileSystem fileSystem, Iterable inputFiles, boolean testFile) { + for (InputFile inputFile : inputFiles) { + ((DefaultInputFile) inputFile).setType(testFile ? InputFile.Type.TEST : InputFile.Type.MAIN); + ((DefaultFileSystem) fileSystem).add(inputFile); + } + } + + public static List getContentOfFiles(String path, String fileNameBase, int numberOfFiles) throws IOException { + List contentOfFiles = new ArrayList(); + + URL resourceURL = FileTestUtils.class.getResource(path + fileNameBase + "1.scala"); + for (int i = 1; resourceURL != null && i <= numberOfFiles; ) { + try { + contentOfFiles.add(FileUtils.readFileToString(new File(resourceURL.getFile()), Charset.defaultCharset().toString())); + } catch (IOException ioe) { + LOGGER.error("Unexpected I/O exception occurred", ioe); + throw ioe; + } + resourceURL = FileTestUtils.class.getResource(path + fileNameBase + (++i) + ".scala"); + } + + return contentOfFiles; + } +} diff --git a/src/test/resources/baseMetricsSensor/ScalaFile1.scala b/src/test/resources/baseMetricsSensor/ScalaFile1.scala index c739d27..1394668 100644 --- a/src/test/resources/baseMetricsSensor/ScalaFile1.scala +++ b/src/test/resources/baseMetricsSensor/ScalaFile1.scala @@ -1,5 +1,5 @@ -package baseMetricsSensor - -class ScalaFile1 { - +package baseMetricsSensor + +class ScalaFile1 { + } \ No newline at end of file diff --git a/src/test/resources/baseMetricsSensor/ScalaFile2.scala b/src/test/resources/baseMetricsSensor/ScalaFile2.scala index 31a2287..2102458 100644 --- a/src/test/resources/baseMetricsSensor/ScalaFile2.scala +++ b/src/test/resources/baseMetricsSensor/ScalaFile2.scala @@ -1,5 +1,5 @@ -package baseMetricsSensor.otherPackage - -class ScalaFile2 { - +package baseMetricsSensor.otherPackage + +class ScalaFile2 { + } \ No newline at end of file diff --git a/src/test/resources/cpd/Duplications5Tokens.scala b/src/test/resources/cpd/Duplications5Tokens.scala deleted file mode 100644 index 6a1150c..0000000 --- a/src/test/resources/cpd/Duplications5Tokens.scala +++ /dev/null @@ -1,6 +0,0 @@ -class Duplications5Tokens { - val i = 0; - - - val j = 0; -} diff --git a/src/test/resources/cpd/Empty.scala b/src/test/resources/cpd/Empty.scala new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/cpd/NewlineToken.scala b/src/test/resources/cpd/NewlineToken.scala index dec3a84..810e52d 100644 --- a/src/test/resources/cpd/NewlineToken.scala +++ b/src/test/resources/cpd/NewlineToken.scala @@ -1,5 +1,5 @@ -class NewlineToken { - val i = 42 - val j = 1000 - println("hehe") -} +class NewlineToken { + val i = 42 + val j = 1000 + println("hehe") +} diff --git a/src/test/resources/cpd/NewlinesToken.scala b/src/test/resources/cpd/NewlinesToken.scala index f0ad4f7..9f115e6 100644 --- a/src/test/resources/cpd/NewlinesToken.scala +++ b/src/test/resources/cpd/NewlinesToken.scala @@ -1,6 +1,7 @@ -class NewlinesToken { - val i = 42 - val j = 1000 - - println("hehe") -} +class NewlinesToken { + val i = 42 + val j = 1000 + + println("hehe") + println("") +} diff --git a/src/test/resources/cpd/NoDuplications.scala b/src/test/resources/cpd/NoDuplications.scala deleted file mode 100644 index 638d321..0000000 --- a/src/test/resources/cpd/NoDuplications.scala +++ /dev/null @@ -1,3 +0,0 @@ -class NoDuplications { - val i = 0 -} diff --git a/src/test/resources/cpd/TwoDuplicatedBlocks.scala b/src/test/resources/cpd/TwoDuplicatedBlocks.scala deleted file mode 100644 index 856335f..0000000 --- a/src/test/resources/cpd/TwoDuplicatedBlocks.scala +++ /dev/null @@ -1,11 +0,0 @@ -class TwoDuplicatedBlocks { - val i = 42 - println("Foo") - println("Bar"); - val j = 0; - - val k = 42 - println("John") - println("Smith"); - val l = 0; -} diff --git a/src/test/resources/lexer/HeaderCommentWithCodeBefore.txt b/src/test/resources/lexer/HeaderCommentWithCodeBefore.txt index e1ac767..36d317a 100644 --- a/src/test/resources/lexer/HeaderCommentWithCodeBefore.txt +++ b/src/test/resources/lexer/HeaderCommentWithCodeBefore.txt @@ -1,8 +1,8 @@ -public class HelloWorld { - val a = 1 -} - -/* - * This comment describes the - * content of the file. +public class HelloWorld { + val a = 1 +} + +/* + * This comment describes the + * content of the file. */ \ No newline at end of file diff --git a/src/test/resources/lexer/HeaderCommentWithWrongStart.txt b/src/test/resources/lexer/HeaderCommentWithWrongStart.txt index c706531..0cce417 100644 --- a/src/test/resources/lexer/HeaderCommentWithWrongStart.txt +++ b/src/test/resources/lexer/HeaderCommentWithWrongStart.txt @@ -1,4 +1,4 @@ -/** - * This comment describes the - * content of the file. +/** + * This comment describes the + * content of the file. */ \ No newline at end of file diff --git a/src/test/resources/lexer/SimpleHeaderComment.txt b/src/test/resources/lexer/SimpleHeaderComment.txt index 366ad3a..ee73072 100644 --- a/src/test/resources/lexer/SimpleHeaderComment.txt +++ b/src/test/resources/lexer/SimpleHeaderComment.txt @@ -1,4 +1,4 @@ -/* - * This comment describes the - * content of the file. +/* + * This comment describes the + * content of the file. */ \ No newline at end of file diff --git a/src/test/resources/packageResolver/DeepNestedPackageDeclaration.txt b/src/test/resources/packageResolver/DeepNestedPackageDeclaration.txt index 4b877bb..190e6c2 100644 --- a/src/test/resources/packageResolver/DeepNestedPackageDeclaration.txt +++ b/src/test/resources/packageResolver/DeepNestedPackageDeclaration.txt @@ -1,18 +1,18 @@ -package one.two.three.four { - - package five.six.seven { - - package eight.nine.ten.eleven { - - package twelve.thirteen.fourteen { - - package fifteen.sixteen { - - object A { - val b = 1 - } - } - } - } - } +package one.two.three.four { + + package five.six.seven { + + package eight.nine.ten.eleven { + + package twelve.thirteen.fourteen { + + package fifteen.sixteen { + + object A { + val b = 1 + } + } + } + } + } } \ No newline at end of file diff --git a/src/test/resources/packageResolver/DeepNestedPackageDeclarationWithObjectBetween.txt b/src/test/resources/packageResolver/DeepNestedPackageDeclarationWithObjectBetween.txt index af000f4..24a5400 100644 --- a/src/test/resources/packageResolver/DeepNestedPackageDeclarationWithObjectBetween.txt +++ b/src/test/resources/packageResolver/DeepNestedPackageDeclarationWithObjectBetween.txt @@ -1,22 +1,22 @@ -package one { - - package two.three.four.five.six.seven { - - package eight { - - object B - - package nine.ten.eleven.twelve.thirteen.fourteen { - - object C - - package fifteen.sixteen { - - object A { - val b = 1 - } - } - } - } - } +package one { + + package two.three.four.five.six.seven { + + package eight { + + object B + + package nine.ten.eleven.twelve.thirteen.fourteen { + + object C + + package fifteen.sixteen { + + object A { + val b = 1 + } + } + } + } + } } \ No newline at end of file diff --git a/src/test/resources/packageResolver/NestedPackageDeclaration.txt b/src/test/resources/packageResolver/NestedPackageDeclaration.txt index 40a9b04..b498581 100644 --- a/src/test/resources/packageResolver/NestedPackageDeclaration.txt +++ b/src/test/resources/packageResolver/NestedPackageDeclaration.txt @@ -1,9 +1,9 @@ -package one.two { - - package three { - - object A { - val b = 1 - } - } +package one.two { + + package three { + + object A { + val b = 1 + } + } } \ No newline at end of file diff --git a/src/test/resources/packageResolver/NestedPackageDeclarationWithObjectBetween.txt b/src/test/resources/packageResolver/NestedPackageDeclarationWithObjectBetween.txt index 1c1ae97..ef704b3 100644 --- a/src/test/resources/packageResolver/NestedPackageDeclarationWithObjectBetween.txt +++ b/src/test/resources/packageResolver/NestedPackageDeclarationWithObjectBetween.txt @@ -1,11 +1,11 @@ -package one.two { - - object B - - package three { - - object A { - val b = 1 - } - } +package one.two { + + object B + + package three { + + object A { + val b = 1 + } + } } \ No newline at end of file diff --git a/src/test/resources/scalaFile/ScalaFile1.scala b/src/test/resources/scalaFile/ScalaFile1.scala index 0d30e45..4e0c738 100644 --- a/src/test/resources/scalaFile/ScalaFile1.scala +++ b/src/test/resources/scalaFile/ScalaFile1.scala @@ -1,5 +1,5 @@ -package scalaFile - -class ScalaFile1 { - +package scalaFile + +class ScalaFile1 { + } \ No newline at end of file diff --git a/src/test/resources/scalaFile/ScalaTestFile1.scala b/src/test/resources/scalaFile/ScalaTestFile1.scala index 5f58e94..1a66a43 100644 --- a/src/test/resources/scalaFile/ScalaTestFile1.scala +++ b/src/test/resources/scalaFile/ScalaTestFile1.scala @@ -1,5 +1,5 @@ -package scalaFile - -class ScalaTestFile1 { - +package scalaFile + +class ScalaTestFile1 { + } \ No newline at end of file diff --git a/src/test/resources/scalaSourceImporter/JavaMainFile1.java b/src/test/resources/scalaSourceImporter/JavaMainFile1.java index ad3a4b5..3ec2f90 100644 --- a/src/test/resources/scalaSourceImporter/JavaMainFile1.java +++ b/src/test/resources/scalaSourceImporter/JavaMainFile1.java @@ -1,5 +1,5 @@ -package scalaSourceImporter; - -public class JavaMainFile1 { - +package scalaSourceImporter; + +public class JavaMainFile1 { + } \ No newline at end of file diff --git a/src/test/resources/scalaSourceImporter/JavaTestFile1.java b/src/test/resources/scalaSourceImporter/JavaTestFile1.java index 742f8b0..88956db 100644 --- a/src/test/resources/scalaSourceImporter/JavaTestFile1.java +++ b/src/test/resources/scalaSourceImporter/JavaTestFile1.java @@ -1,5 +1,5 @@ -package scalaSourceImporter; - -public class JavaTestFile1 { - +package scalaSourceImporter; + +public class JavaTestFile1 { + } \ No newline at end of file diff --git a/src/test/resources/scalaSourceImporter/MainFile1.scala b/src/test/resources/scalaSourceImporter/MainFile1.scala index 3cbae7a..43bebd3 100644 --- a/src/test/resources/scalaSourceImporter/MainFile1.scala +++ b/src/test/resources/scalaSourceImporter/MainFile1.scala @@ -1,5 +1,5 @@ -package scalaSourceImporter - -class MainFile1 { - +package scalaSourceImporter + +class MainFile1 { + } \ No newline at end of file diff --git a/src/test/resources/scalaSourceImporter/MainFile3.scala b/src/test/resources/scalaSourceImporter/MainFile3.scala index a0d7a39..86b7535 100644 --- a/src/test/resources/scalaSourceImporter/MainFile3.scala +++ b/src/test/resources/scalaSourceImporter/MainFile3.scala @@ -1,5 +1,5 @@ -package scalaSourceImporter - -class MainFile3 { - +package scalaSourceImporter + +class MainFile3 { + } \ No newline at end of file diff --git a/src/test/resources/scalaSourceImporter/TestFile2.scala b/src/test/resources/scalaSourceImporter/TestFile2.scala index dfc8fc3..5d146fb 100644 --- a/src/test/resources/scalaSourceImporter/TestFile2.scala +++ b/src/test/resources/scalaSourceImporter/TestFile2.scala @@ -1,5 +1,5 @@ -package scalaSourceImporter - -class TestFile2 { - +package scalaSourceImporter + +class TestFile2 { + } \ No newline at end of file diff --git a/src/test/resources/scalaSourceImporter/TestFile3.scala b/src/test/resources/scalaSourceImporter/TestFile3.scala index b7fe94d..b6f99ab 100644 --- a/src/test/resources/scalaSourceImporter/TestFile3.scala +++ b/src/test/resources/scalaSourceImporter/TestFile3.scala @@ -1,5 +1,5 @@ -package scalaSourceImporter - -class TestFile3 { - +package scalaSourceImporter + +class TestFile3 { + } \ No newline at end of file diff --git a/src/test/scala/org/sonar/plugins/scala/language/CodeDetectorSpec.scala b/src/test/scala/org/sonar/plugins/scala/language/CodeDetectorSpec.scala index ad3a8af..5f738e7 100644 --- a/src/test/scala/org/sonar/plugins/scala/language/CodeDetectorSpec.scala +++ b/src/test/scala/org/sonar/plugins/scala/language/CodeDetectorSpec.scala @@ -1,60 +1,60 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language - -import org.junit.runner.RunWith -import org.scalatest.{ShouldMatchers, FlatSpec} -import org.scalatest.junit.JUnitRunner - -@RunWith(classOf[JUnitRunner]) -class CodeDetectorSpec extends FlatSpec with ShouldMatchers { - - "A code detector" should "detect a simple variable declaration" in { - CodeDetector.hasDetectedCode("val a = 1") should be (true) - } - - it should "detect a simple function call" in { - CodeDetector.hasDetectedCode("list.map(_ + \"Hello World\")") should be (true) - } - - it should "detect a simple value assignment" in { - CodeDetector.hasDetectedCode("a = 1 + 2") should be (true) - } - - it should "detect a simple package declaration" in { - CodeDetector.hasDetectedCode("package hello.world") should be (true) - } - - it should "not detect any code in a normal text" in { - CodeDetector.hasDetectedCode("this is just a normal text") should be (false) - } - - it should "not detect any code in a normal comment text" in { - CodeDetector.hasDetectedCode("// this is a normal comment") should be (false) - } - - it should "detect a while loop" in { - CodeDetector.hasDetectedCode("while (i == 2) { println(i); }") should be (true) - } - - it should "detect a for loop" in { - CodeDetector.hasDetectedCode("for (i <- 1 to 10) { println(i); }") should be (true) - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language + +import org.junit.runner.RunWith +import org.scalatest.{ShouldMatchers, FlatSpec} +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class CodeDetectorSpec extends FlatSpec with ShouldMatchers { + + "A code detector" should "detect a simple variable declaration" in { + CodeDetector.hasDetectedCode("val a = 1") should be (true) + } + + it should "detect a simple function call" in { + CodeDetector.hasDetectedCode("list.map(_ + \"Hello World\")") should be (true) + } + + it should "detect a simple value assignment" in { + CodeDetector.hasDetectedCode("a = 1 + 2") should be (true) + } + + it should "detect a simple package declaration" in { + CodeDetector.hasDetectedCode("package hello.world") should be (true) + } + + it should "not detect any code in a normal text" in { + CodeDetector.hasDetectedCode("this is just a normal text") should be (false) + } + + it should "not detect any code in a normal comment text" in { + CodeDetector.hasDetectedCode("// this is a normal comment") should be (false) + } + + it should "detect a while loop" in { + CodeDetector.hasDetectedCode("while (i == 2) { println(i); }") should be (true) + } + + it should "detect a for loop" in { + CodeDetector.hasDetectedCode("for (i <- 1 to 10) { println(i); }") should be (true) + } } \ No newline at end of file diff --git a/src/test/scala/org/sonar/plugins/scala/language/PackageResolverSpec.scala b/src/test/scala/org/sonar/plugins/scala/language/PackageResolverSpec.scala index 39e88f2..2e747aa 100644 --- a/src/test/scala/org/sonar/plugins/scala/language/PackageResolverSpec.scala +++ b/src/test/scala/org/sonar/plugins/scala/language/PackageResolverSpec.scala @@ -1,59 +1,59 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.language - -import org.junit.runner.RunWith -import org.scalatest.{ShouldMatchers, FlatSpec} -import org.scalatest.junit.JUnitRunner - -import org.sonar.plugins.scala.util.FileTestUtils; - -@RunWith(classOf[JUnitRunner]) -class PackageResolverSpec extends FlatSpec with ShouldMatchers { - - "A package resolver" should "resolve the package name of a simple package declaration" in { - getPackageNameOf("SimplePackageDeclaration") should equal ("one") - } - - it should "resolve the package name of a nested package declaration" in { - getPackageNameOf("NestedPackageDeclaration") should equal ("one.two.three") - } - - it should "resolve the package name of a deep nested package declaration" in { - getPackageNameOf("DeepNestedPackageDeclaration") should equal ("one.two.three.four.five.six." + - "seven.eight.nine.ten.eleven.twelve.thirteen.fourteen.fifteen.sixteen") - } - - it should "resolve the upper package name of a nested package declaration with " + - "an object declaration between" in { - getPackageNameOf("NestedPackageDeclarationWithObjectBetween") should equal ("one.two") - } - - it should "resolve the package name of a deep nested package declaration with" + - "an object declaration between" in { - getPackageNameOf("DeepNestedPackageDeclarationWithObjectBetween") should equal ("one.two.three." + - "four.five.six.seven.eight") - } - - private def getPackageNameOf(fileName: String) = { - val path = FileTestUtils.getRelativePath("/packageResolver/" + fileName + ".txt") - PackageResolver.resolvePackageNameOfFile(path) - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.language + +import org.junit.runner.RunWith +import org.scalatest.{ShouldMatchers, FlatSpec} +import org.scalatest.junit.JUnitRunner + +import org.sonar.plugins.scala.util.FileTestUtils; + +@RunWith(classOf[JUnitRunner]) +class PackageResolverSpec extends FlatSpec with ShouldMatchers { + + "A package resolver" should "resolve the package name of a simple package declaration" in { + getPackageNameOf("SimplePackageDeclaration") should equal ("one") + } + + it should "resolve the package name of a nested package declaration" in { + getPackageNameOf("NestedPackageDeclaration") should equal ("one.two.three") + } + + it should "resolve the package name of a deep nested package declaration" in { + getPackageNameOf("DeepNestedPackageDeclaration") should equal ("one.two.three.four.five.six." + + "seven.eight.nine.ten.eleven.twelve.thirteen.fourteen.fifteen.sixteen") + } + + it should "resolve the upper package name of a nested package declaration with " + + "an object declaration between" in { + getPackageNameOf("NestedPackageDeclarationWithObjectBetween") should equal ("one.two") + } + + it should "resolve the package name of a deep nested package declaration with" + + "an object declaration between" in { + getPackageNameOf("DeepNestedPackageDeclarationWithObjectBetween") should equal ("one.two.three." + + "four.five.six.seven.eight") + } + + private def getPackageNameOf(fileName: String) = { + val path = FileTestUtils.getRelativePath("/packageResolver/" + fileName + ".txt") + PackageResolver.resolvePackageNameOfFile(path) + } } \ No newline at end of file diff --git a/src/test/scala/org/sonar/plugins/scala/metrics/ComplexityCalculatorSpec.scala b/src/test/scala/org/sonar/plugins/scala/metrics/ComplexityCalculatorSpec.scala index 4322a31..06513e7 100644 --- a/src/test/scala/org/sonar/plugins/scala/metrics/ComplexityCalculatorSpec.scala +++ b/src/test/scala/org/sonar/plugins/scala/metrics/ComplexityCalculatorSpec.scala @@ -1,162 +1,162 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics - -import org.junit.runner.RunWith -import org.scalatest.{ShouldMatchers, FlatSpec} -import org.scalatest.junit.JUnitRunner - -@RunWith(classOf[JUnitRunner]) -class ComplexityCalculatorSpec extends FlatSpec with ShouldMatchers { - - "A complexity calculator" should "calculate complexity of if expression" in { - ComplexityCalculator.measureComplexity("if (2 == 3) println(123)") should be (1) - } - - it should "calculate complexity of for loop" in { - ComplexityCalculator.measureComplexity("for (i <- 1 to 10) println(i)") should be (1) - } - - it should "calculate complexity of while loop" in { - val source = """var i = 0 - while (i < 10) { - println(i) - i += 1 - }""" - ComplexityCalculator.measureComplexity(source) should be (1) - } - - it should "calculate complexity of do loop" in { - val source = """var i = 0 - do { - println(i) - i += 1 - } while (i < 10)""" - ComplexityCalculator.measureComplexity(source) should be (1) - } - - it should "calculate complexity of throw expression" in { - ComplexityCalculator.measureComplexity("throw new RuntimeException()") should be (1) - } - - it should "calculate complexity of while loop with an if condition and throw expression" in { - val source = """var i = 0 - while (i < 10) { - println(i) - i += 1 - if (i == 9) - throw new RuntimeException() - }""" - ComplexityCalculator.measureComplexity(source) should be (3) - } - - it should "calculate complexity of function definition" in { - ComplexityCalculator.measureComplexity("def inc(i: Int) = i + 1") should be (1) - } - - it should "calculate complexity of function definition with an if condition" in { - val source = """def inc(i: Int) = { - if (i == 0) { - i + 2 - } else { - i + 1 - } - }""" - ComplexityCalculator.measureComplexity(source) should be (2) - } - - it should "calculate complexity of function definition and its whole body" in { - val source = """def inc(i: Int) = { - if (i == 0) { - i + 2 - } else { - while (i < 10) { - if (i == 9) - throw new RuntimeException() - i + 1 - } - } - }""" - ComplexityCalculator.measureComplexity(source) should be (5) - } - - it should "calculate complexity distribution of one function" in { - val source = """def inc(i: Int) = { - if (i == 0) { - i + 2 - } else { - i + 1 - } - }""" - - ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") - } - - it should "calculate complexity distribution of two functions" in { - val source = """def inc(i: Int) = { - if (i == 0) { - i + 2 - } else { - i + 1 - } - } - - def dec(i: Int) = i - 1""" - - ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("1=1") - ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") - } - - it should "calculate complexity distribution of all functions" in { - val source = """def inc(i: Int) = { - if (i == 0) { - i + 2 - } else { - i + 1 - } - } - - def dec(i: Int) = i - 1 - def dec2(i: Int) = i - 2 - def dec3(i: Int) = i - 3""" - - ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("1=3") - ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") - } - - it should "calculate complexity distribution of all functions nested in a class" in { - val source = """class A { - def inc(i: Int) = { - if (i == 0) { - i + 2 - } else { - i + 1 - } - } - - def dec(i: Int) = i - 1 - def dec2(i: Int) = i - 2 - def dec3(i: Int) = i - 3 - }""" - - ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("1=3") - ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics + +import org.junit.runner.RunWith +import org.scalatest.{ShouldMatchers, FlatSpec} +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class ComplexityCalculatorSpec extends FlatSpec with ShouldMatchers { + + "A complexity calculator" should "calculate complexity of if expression" in { + ComplexityCalculator.measureComplexity("if (2 == 3) println(123)") should be (1) + } + + it should "calculate complexity of for loop" in { + ComplexityCalculator.measureComplexity("for (i <- 1 to 10) println(i)") should be (1) + } + + it should "calculate complexity of while loop" in { + val source = """var i = 0 + while (i < 10) { + println(i) + i += 1 + }""" + ComplexityCalculator.measureComplexity(source) should be (1) + } + + it should "calculate complexity of do loop" in { + val source = """var i = 0 + do { + println(i) + i += 1 + } while (i < 10)""" + ComplexityCalculator.measureComplexity(source) should be (1) + } + + it should "calculate complexity of throw expression" in { + ComplexityCalculator.measureComplexity("throw new RuntimeException()") should be (1) + } + + it should "calculate complexity of while loop with an if condition and throw expression" in { + val source = """var i = 0 + while (i < 10) { + println(i) + i += 1 + if (i == 9) + throw new RuntimeException() + }""" + ComplexityCalculator.measureComplexity(source) should be (3) + } + + it should "calculate complexity of function definition" in { + ComplexityCalculator.measureComplexity("def inc(i: Int) = i + 1") should be (1) + } + + it should "calculate complexity of function definition with an if condition" in { + val source = """def inc(i: Int) = { + if (i == 0) { + i + 2 + } else { + i + 1 + } + }""" + ComplexityCalculator.measureComplexity(source) should be (2) + } + + it should "calculate complexity of function definition and its whole body" in { + val source = """def inc(i: Int) = { + if (i == 0) { + i + 2 + } else { + while (i < 10) { + if (i == 9) + throw new RuntimeException() + i + 1 + } + } + }""" + ComplexityCalculator.measureComplexity(source) should be (5) + } + + it should "calculate complexity distribution of one function" in { + val source = """def inc(i: Int) = { + if (i == 0) { + i + 2 + } else { + i + 1 + } + }""" + + ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") + } + + it should "calculate complexity distribution of two functions" in { + val source = """def inc(i: Int) = { + if (i == 0) { + i + 2 + } else { + i + 1 + } + } + + def dec(i: Int) = i - 1""" + + ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("1=1") + ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") + } + + it should "calculate complexity distribution of all functions" in { + val source = """def inc(i: Int) = { + if (i == 0) { + i + 2 + } else { + i + 1 + } + } + + def dec(i: Int) = i - 1 + def dec2(i: Int) = i - 2 + def dec3(i: Int) = i - 3""" + + ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("1=3") + ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") + } + + it should "calculate complexity distribution of all functions nested in a class" in { + val source = """class A { + def inc(i: Int) = { + if (i == 0) { + i + 2 + } else { + i + 1 + } + } + + def dec(i: Int) = i - 1 + def dec2(i: Int) = i - 2 + def dec3(i: Int) = i - 3 + }""" + + ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("1=3") + ComplexityCalculator.measureComplexityOfFunctions(source).getMeasure.getData should include ("2=1") + } } \ No newline at end of file diff --git a/src/test/scala/org/sonar/plugins/scala/metrics/PublicApiCounterSpec.scala b/src/test/scala/org/sonar/plugins/scala/metrics/PublicApiCounterSpec.scala index a8002b8..263feff 100644 --- a/src/test/scala/org/sonar/plugins/scala/metrics/PublicApiCounterSpec.scala +++ b/src/test/scala/org/sonar/plugins/scala/metrics/PublicApiCounterSpec.scala @@ -1,141 +1,141 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics - -import org.junit.runner.RunWith -import org.scalatest.{ShouldMatchers, FlatSpec} -import org.scalatest.junit.JUnitRunner - -@RunWith(classOf[JUnitRunner]) -class PublicApiCounterSpec extends FlatSpec with ShouldMatchers { - - "A public api counter" should "count a simple function declaration" in { - PublicApiCounter.countPublicApi("def test = 42") should be (1) - } - - it should "count a simple method declaration" in { - PublicApiCounter.countPublicApi("def test { println(42) }") should be (1) - } - - it should "count a simple value declaration" in { - PublicApiCounter.countPublicApi("val maybeImportantNumber = 42") should be (1) - } - - it should "not count a private value declaration" in { - PublicApiCounter.countPublicApi("private val maybeImportantNumber = 42") should be (0) - } - - it should "not count a private function declaration" in { - PublicApiCounter.countPublicApi("private def test = 42") should be (0) - } - - it should "not count a private method declaration" in { - PublicApiCounter.countPublicApi("private def test { println(42) }") should be (0) - } - - it should "count a class declaration" in { - PublicApiCounter.countPublicApi("class A {}") should be (1) - } - - it should "count an object declaration" in { - PublicApiCounter.countPublicApi("object A {}") should be (1) - } - - it should "count a trait declaration" in { - PublicApiCounter.countPublicApi("trait A {}") should be (1) - } - - it should "not count a private class declaration" in { - PublicApiCounter.countPublicApi("private class A {}") should be (0) - } - - it should "not count a private object declaration" in { - PublicApiCounter.countPublicApi("private object A {}") should be (0) - } - - it should "not count a private trait declaration" in { - PublicApiCounter.countPublicApi("private trait A {}") should be (0) - } - - it should "count an undocumented class declaration" in { - PublicApiCounter.countUndocumentedPublicApi("class A {}") should be (1) - } - - it should "count an undocumented class declaration with package declaration before" in { - val source = """package a.b.c - - class A {}""" - PublicApiCounter.countUndocumentedPublicApi(source) should be (1) - } - - it should "not count a documented class declaration with package declaration before as undocumented one" in { - val source = """package a.b.c - - /** - * This is a comment of a public api member. - */ - class A {}""" - PublicApiCounter.countUndocumentedPublicApi(source) should be (0) - } - - it should "count all public api members of class and its undocumented ones" in { - val source = """package a.b.c - - /** - * This is a comment of a public api member. - */ - class A { - - /** - * Well, don't panic. ;-) - */ - val meaningOfLife = 42 - - val b = "test" - - def helloWorld { printString("Hello World!") } - - private def printString(str: String) { println(str) } - }""" - - PublicApiCounter.countPublicApi(source) should be (4) - PublicApiCounter.countUndocumentedPublicApi(source) should be (2) - } - - it should "not count nested function and method declarations" in { - val source ="""def test = { - def a = 12 + 1 - def b = 13 + 1 - - a + b + 42 - }""" - PublicApiCounter.countPublicApi(source) should be (1) - } - - it should "not count nested value declarations" in { - val source ="""val test = { - def a = 12 + 1 - def b = 13 + 1 - - a + b + 42 - }""" - PublicApiCounter.countPublicApi(source) should be (1) - } -} +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics + +import org.junit.runner.RunWith +import org.scalatest.{ShouldMatchers, FlatSpec} +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class PublicApiCounterSpec extends FlatSpec with ShouldMatchers { + + "A public api counter" should "count a simple function declaration" in { + PublicApiCounter.countPublicApi("def test = 42") should be (1) + } + + it should "count a simple method declaration" in { + PublicApiCounter.countPublicApi("def test { println(42) }") should be (1) + } + + it should "count a simple value declaration" in { + PublicApiCounter.countPublicApi("val maybeImportantNumber = 42") should be (1) + } + + it should "not count a private value declaration" in { + PublicApiCounter.countPublicApi("private val maybeImportantNumber = 42") should be (0) + } + + it should "not count a private function declaration" in { + PublicApiCounter.countPublicApi("private def test = 42") should be (0) + } + + it should "not count a private method declaration" in { + PublicApiCounter.countPublicApi("private def test { println(42) }") should be (0) + } + + it should "count a class declaration" in { + PublicApiCounter.countPublicApi("class A {}") should be (1) + } + + it should "count an object declaration" in { + PublicApiCounter.countPublicApi("object A {}") should be (1) + } + + it should "count a trait declaration" in { + PublicApiCounter.countPublicApi("trait A {}") should be (1) + } + + it should "not count a private class declaration" in { + PublicApiCounter.countPublicApi("private class A {}") should be (0) + } + + it should "not count a private object declaration" in { + PublicApiCounter.countPublicApi("private object A {}") should be (0) + } + + it should "not count a private trait declaration" in { + PublicApiCounter.countPublicApi("private trait A {}") should be (0) + } + + it should "count an undocumented class declaration" in { + PublicApiCounter.countUndocumentedPublicApi("class A {}") should be (1) + } + + it should "count an undocumented class declaration with package declaration before" in { + val source = """package a.b.c + + class A {}""" + PublicApiCounter.countUndocumentedPublicApi(source) should be (1) + } + + it should "not count a documented class declaration with package declaration before as undocumented one" in { + val source = """package a.b.c + + /** + * This is a comment of a public api member. + */ + class A {}""" + PublicApiCounter.countUndocumentedPublicApi(source) should be (0) + } + + it should "count all public api members of class and its undocumented ones" in { + val source = """package a.b.c + + /** + * This is a comment of a public api member. + */ + class A { + + /** + * Well, don't panic. ;-) + */ + val meaningOfLife = 42 + + val b = "test" + + def helloWorld { printString("Hello World!") } + + private def printString(str: String) { println(str) } + }""" + + PublicApiCounter.countPublicApi(source) should be (4) + PublicApiCounter.countUndocumentedPublicApi(source) should be (2) + } + + it should "not count nested function and method declarations" in { + val source ="""def test = { + def a = 12 + 1 + def b = 13 + 1 + + a + b + 42 + }""" + PublicApiCounter.countPublicApi(source) should be (1) + } + + it should "not count nested value declarations" in { + val source ="""val test = { + def a = 12 + 1 + def b = 13 + 1 + + a + b + 42 + }""" + PublicApiCounter.countPublicApi(source) should be (1) + } +} diff --git a/src/test/scala/org/sonar/plugins/scala/metrics/StatementCounterSpec.scala b/src/test/scala/org/sonar/plugins/scala/metrics/StatementCounterSpec.scala index f71115b..c81b8fa 100644 --- a/src/test/scala/org/sonar/plugins/scala/metrics/StatementCounterSpec.scala +++ b/src/test/scala/org/sonar/plugins/scala/metrics/StatementCounterSpec.scala @@ -1,173 +1,173 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.metrics - -import org.junit.runner.RunWith -import org.scalatest.{ShouldMatchers, FlatSpec} -import org.scalatest.junit.JUnitRunner - -@RunWith(classOf[JUnitRunner]) -class StatementCounterSpec extends FlatSpec with ShouldMatchers { - - "A statement counter" should "count a simple assignment as a statement" in { - StatementCounter.countStatements("a = 1") should be (1) - } - - it should "count a simple method call as a statement" in { - StatementCounter.countStatements("println(123)") should be (1) - } - - it should "not count a simple variable declaration as a statement" in { - StatementCounter.countStatements("var a") should be (0) - } - - it should "count a simple variable declaration with assignment as a statement" in { - StatementCounter.countStatements("var a = 2") should be (1) - } - - it should "count a while loop as a statement" in { - StatementCounter.countStatements("while (1 == 1) {}") should be (1) - } - - it should "count a for loop as a statement" in { - StatementCounter.countStatements("for (i <- 1 to 10) {}") should be (1) - } - - it should "count a while loop as a statement and all statements in loop body" in { - val source = """ - while (1 == 1) { - val a = inc(2) - }""" - StatementCounter.countStatements(source) should be (2) - } - - it should "count a for loop as a statement and all statements in loop body" in { - val source = """ - for (i <- 1 to 10) { - val a = inc(2) - }""" - StatementCounter.countStatements(source) should be (2) - } - - it should "count if as a statement" in { - val source = """ - if (1 == 1) - println()""" - StatementCounter.countStatements(source) should be (2) - } - - it should "count an if block as a statement and all statements in its body" in { - val source = """ - if (1 + 2 < 4) { - val a = inc(2) - println(3) - def test = { 1 + 2 } - }""" - StatementCounter.countStatements(source) should be (4) - } - - it should "count a simple if else block as a statement" in { - val source = """ - if (1+2 < 4) - println("Hello World") - else - println("123")""" - StatementCounter.countStatements(source) should be (4) - } - - it should "count an if else block as a statement and all statements in its body" in { - val source = """ - if (1 + 2 < 4) { - val a = inc(2) - println("Hello World") - def test = 1 + 2 - } else { - def test2 = 1 - val b = test2 - }""" - StatementCounter.countStatements(source) should be (7) - } - - it should "count all statements in body of a function definition" in { - val source = """ - def test(i: Int) = { - val a = i + 42 - println(a) - println(i + 42) - a - }""" - StatementCounter.countStatements(source) should be (4) - } - - it should "count all statements in body of a value definition" in { - val source = """ - val test = { - val a = i + 42 - println(a) - println(i + 42) - a - }""" - StatementCounter.countStatements(source) should be (4) - } - - it should "count for comprehension with yield statement" in { - val source = "for (x <- List(1, 2, 3, 4, 5) if (x % 2 != 0)) yield x" - StatementCounter.countStatements(source) should be (2) - } - - it should "count for comprehension with more complex yield statement" in { - val source = "for (x <- List(1, 2, 3, 4, 5) if (x % 2 != 0)) yield x + inc(x)" - StatementCounter.countStatements(source) should be (2) - } - - it should "count for comprehension with yield statement where return value is only a literal" in { - val source = "for (x <- List(1, 2, 3, 4, 5) if (x % 2 != 0)) yield 2" - StatementCounter.countStatements(source) should be (2) - } - - it should "count foreach function call on a list as a statement" in { - val source = """ - myList.foreach {i => - println(i) - val a = i + 1 - println("inc: " + i) - }""" - StatementCounter.countStatements(source) should be (4) - } - - it should "count foreach function call and all statements in its body" in { - val source = """ - def foo() = { - List("Hello", "World", "!").foreach(word => - if (find(By(name, word)).isEmpty) - create.name(word).save - ) - }""" - StatementCounter.countStatements(source) should be (3) - } - - it should "count function call in a function definition nested in an object" in { - val source = """ - object name extends MappedPoliteString(this, 100) { - override def validations = valMinLen(1, S.?("attributeName")) _ :: Nil - }""" - StatementCounter.countStatements(source) should be (2) - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.metrics + +import org.junit.runner.RunWith +import org.scalatest.{ShouldMatchers, FlatSpec} +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class StatementCounterSpec extends FlatSpec with ShouldMatchers { + + "A statement counter" should "count a simple assignment as a statement" in { + StatementCounter.countStatements("a = 1") should be (1) + } + + it should "count a simple method call as a statement" in { + StatementCounter.countStatements("println(123)") should be (1) + } + + it should "not count a simple variable declaration as a statement" in { + StatementCounter.countStatements("var a") should be (0) + } + + it should "count a simple variable declaration with assignment as a statement" in { + StatementCounter.countStatements("var a = 2") should be (1) + } + + it should "count a while loop as a statement" in { + StatementCounter.countStatements("while (1 == 1) {}") should be (1) + } + + it should "count a for loop as a statement" in { + StatementCounter.countStatements("for (i <- 1 to 10) {}") should be (1) + } + + it should "count a while loop as a statement and all statements in loop body" in { + val source = """ + while (1 == 1) { + val a = inc(2) + }""" + StatementCounter.countStatements(source) should be (2) + } + + it should "count a for loop as a statement and all statements in loop body" in { + val source = """ + for (i <- 1 to 10) { + val a = inc(2) + }""" + StatementCounter.countStatements(source) should be (2) + } + + it should "count if as a statement" in { + val source = """ + if (1 == 1) + println()""" + StatementCounter.countStatements(source) should be (2) + } + + it should "count an if block as a statement and all statements in its body" in { + val source = """ + if (1 + 2 < 4) { + val a = inc(2) + println(3) + def test = { 1 + 2 } + }""" + StatementCounter.countStatements(source) should be (4) + } + + it should "count a simple if else block as a statement" in { + val source = """ + if (1+2 < 4) + println("Hello World") + else + println("123")""" + StatementCounter.countStatements(source) should be (4) + } + + it should "count an if else block as a statement and all statements in its body" in { + val source = """ + if (1 + 2 < 4) { + val a = inc(2) + println("Hello World") + def test = 1 + 2 + } else { + def test2 = 1 + val b = test2 + }""" + StatementCounter.countStatements(source) should be (7) + } + + it should "count all statements in body of a function definition" in { + val source = """ + def test(i: Int) = { + val a = i + 42 + println(a) + println(i + 42) + a + }""" + StatementCounter.countStatements(source) should be (4) + } + + it should "count all statements in body of a value definition" in { + val source = """ + val test = { + val a = i + 42 + println(a) + println(i + 42) + a + }""" + StatementCounter.countStatements(source) should be (4) + } + + it should "count for comprehension with yield statement" in { + val source = "for (x <- List(1, 2, 3, 4, 5) if (x % 2 != 0)) yield x" + StatementCounter.countStatements(source) should be (2) + } + + it should "count for comprehension with more complex yield statement" in { + val source = "for (x <- List(1, 2, 3, 4, 5) if (x % 2 != 0)) yield x + inc(x)" + StatementCounter.countStatements(source) should be (2) + } + + it should "count for comprehension with yield statement where return value is only a literal" in { + val source = "for (x <- List(1, 2, 3, 4, 5) if (x % 2 != 0)) yield 2" + StatementCounter.countStatements(source) should be (2) + } + + it should "count foreach function call on a list as a statement" in { + val source = """ + myList.foreach {i => + println(i) + val a = i + 1 + println("inc: " + i) + }""" + StatementCounter.countStatements(source) should be (4) + } + + it should "count foreach function call and all statements in its body" in { + val source = """ + def foo() = { + List("Hello", "World", "!").foreach(word => + if (find(By(name, word)).isEmpty) + create.name(word).save + ) + }""" + StatementCounter.countStatements(source) should be (3) + } + + it should "count function call in a function definition nested in an object" in { + val source = """ + object name extends MappedPoliteString(this, 100) { + override def validations = valMinLen(1, S.?("attributeName")) _ :: Nil + }""" + StatementCounter.countStatements(source) should be (2) + } } \ No newline at end of file diff --git a/src/test/scala/org/sonar/plugins/scala/util/MetricDistributionSpec.scala b/src/test/scala/org/sonar/plugins/scala/util/MetricDistributionSpec.scala index 40a0570..0950926 100644 --- a/src/test/scala/org/sonar/plugins/scala/util/MetricDistributionSpec.scala +++ b/src/test/scala/org/sonar/plugins/scala/util/MetricDistributionSpec.scala @@ -1,96 +1,96 @@ -/* - * Sonar Scala Plugin - * Copyright (C) 2011 - 2014 All contributors - * dev@sonar.codehaus.org - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.scala.util - -import org.junit.runner.RunWith -import org.scalatest.{ShouldMatchers, FlatSpec} -import org.scalatest.junit.JUnitRunner -import org.sonar.api.measures.CoreMetrics - -@RunWith(classOf[JUnitRunner]) -class MetricDistributionSpec extends FlatSpec with ShouldMatchers { - - val metric = CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION - val ranges = Array[Number](1, 5, 10) - - "A metric distribution" should "increment occurence of value" in { - val distribution = new MetricDistribution(metric, ranges) - distribution.add(1.0) - distribution.getMeasure.getData should be ("1=1;5=0;10=0") - } - - it should "increment occurence of all values" in { - val distribution = new MetricDistribution(metric, ranges) - distribution.add(1.0) - distribution.add(10.0) - distribution.add(5.0) - distribution.getMeasure.getData should be ("1=1;5=1;10=1") - } - - it should "increase occurence of value by submitted number" in { - val distribution = new MetricDistribution(metric, ranges) - distribution.add(1.0, 3) - distribution.getMeasure.getData should be ("1=3;5=0;10=0") - } - - it should "increase occurence of all values by submitted number" in { - val distribution = new MetricDistribution(metric, ranges) - distribution.add(1.0, 3) - distribution.add(10.0, 8) - distribution.add(5.0, 2) - distribution.getMeasure.getData should be ("1=3;5=2;10=8") - } - - it should "increase occurence of value by submitted distribution" in { - val distribution = new MetricDistribution(metric, ranges) - distribution.add(1.0, 3) - - val otherDistribution = new MetricDistribution(metric, ranges) - otherDistribution.add(distribution) - - otherDistribution.getMeasure.getData should be ("1=3;5=0;10=0") - } - - it should "increase occurence of all values by submitted distribution" in { - val distribution = new MetricDistribution(metric, ranges) - distribution.add(1.0, 3) - distribution.add(10.0, 8) - distribution.add(5.0, 2) - - val otherDistribution = new MetricDistribution(metric, ranges) - otherDistribution.add(distribution) - - otherDistribution.getMeasure.getData should be ("1=3;5=2;10=8") - } - - it should "output an empty distribution properly" in { - val distribution = new MetricDistribution(metric, ranges) - distribution.getMeasure.getData should be ("1=0;5=0;10=0") - } - - it should "copy an empty distribution properly" in { - val distribution = new MetricDistribution(metric, ranges) - - val otherDistribution = new MetricDistribution(metric, ranges) - otherDistribution.add(distribution) - - otherDistribution.getMeasure.getData should be ("1=0;5=0;10=0") - } +/* + * Sonar Scala Plugin + * Copyright (C) 2011 - 2014 All contributors + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.scala.util + +import org.junit.runner.RunWith +import org.scalatest.{ShouldMatchers, FlatSpec} +import org.scalatest.junit.JUnitRunner +import org.sonar.api.measures.CoreMetrics + +@RunWith(classOf[JUnitRunner]) +class MetricDistributionSpec extends FlatSpec with ShouldMatchers { + + val metric = CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION + val ranges = Array[Number](1, 5, 10) + + "A metric distribution" should "increment occurence of value" in { + val distribution = new MetricDistribution(metric, ranges) + distribution.add(1.0) + distribution.getMeasure.getData should be ("1=1;5=0;10=0") + } + + it should "increment occurence of all values" in { + val distribution = new MetricDistribution(metric, ranges) + distribution.add(1.0) + distribution.add(10.0) + distribution.add(5.0) + distribution.getMeasure.getData should be ("1=1;5=1;10=1") + } + + it should "increase occurence of value by submitted number" in { + val distribution = new MetricDistribution(metric, ranges) + distribution.add(1.0, 3) + distribution.getMeasure.getData should be ("1=3;5=0;10=0") + } + + it should "increase occurence of all values by submitted number" in { + val distribution = new MetricDistribution(metric, ranges) + distribution.add(1.0, 3) + distribution.add(10.0, 8) + distribution.add(5.0, 2) + distribution.getMeasure.getData should be ("1=3;5=2;10=8") + } + + it should "increase occurence of value by submitted distribution" in { + val distribution = new MetricDistribution(metric, ranges) + distribution.add(1.0, 3) + + val otherDistribution = new MetricDistribution(metric, ranges) + otherDistribution.add(distribution) + + otherDistribution.getMeasure.getData should be ("1=3;5=0;10=0") + } + + it should "increase occurence of all values by submitted distribution" in { + val distribution = new MetricDistribution(metric, ranges) + distribution.add(1.0, 3) + distribution.add(10.0, 8) + distribution.add(5.0, 2) + + val otherDistribution = new MetricDistribution(metric, ranges) + otherDistribution.add(distribution) + + otherDistribution.getMeasure.getData should be ("1=3;5=2;10=8") + } + + it should "output an empty distribution properly" in { + val distribution = new MetricDistribution(metric, ranges) + distribution.getMeasure.getData should be ("1=0;5=0;10=0") + } + + it should "copy an empty distribution properly" in { + val distribution = new MetricDistribution(metric, ranges) + + val otherDistribution = new MetricDistribution(metric, ranges) + otherDistribution.add(distribution) + + otherDistribution.getMeasure.getData should be ("1=0;5=0;10=0") + } } \ No newline at end of file