aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-squid
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2010-09-06 14:08:06 +0000
committersimonbrandhof <simon.brandhof@gmail.com>2010-09-06 14:08:06 +0000
commitaeadc1f9129274949daaa57738c7c4550bdfbc7b (patch)
tree08dadf5ef7474fc41d1d48f74648f1ba8b55f34d /sonar-squid
downloadsonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.tar.gz
sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.zip
SONAR-236 remove deprecated code from checkstyle plugin + display default value of rule parameters in Q profile console
Diffstat (limited to 'sonar-squid')
-rw-r--r--sonar-squid/pom.xml72
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/Squid.java146
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/AnalysisException.java36
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/CheckMessage.java83
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/CodeCheck.java26
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/CodeScanner.java39
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/CodeVisitor.java24
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/Query.java26
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceClass.java31
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceCode.java275
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdge.java139
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdgeUsage.java55
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeIndexer.java25
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeSearchEngine.java30
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeTreeDecorator.java55
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceFile.java54
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceFunction.java32
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceMethod.java38
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourcePackage.java27
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SourceProject.java28
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/api/SquidConfiguration.java39
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByMeasure.java65
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByName.java65
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByParent.java36
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByType.java62
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/indexer/SquidIndex.java66
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/math/MeasuresDistribution.java52
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/AbstractnessFormula.java31
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/AggregationFormula.java28
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/CalculatedMetricFormula.java26
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesDensityFormula.java32
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormula.java28
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/DistanceFormula.java28
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/InstabilityFormula.java31
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/MeanAggregationFormula.java34
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/Measurable.java32
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/Measures.java92
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/Metric.java82
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/MetricDef.java37
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/NoAggregationFormula.java30
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormula.java31
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/measures/SumAggregationFormula.java34
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/CamelCaseDetector.java45
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/CodeRecognizer.java56
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/ContainsDetector.java45
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/Detector.java42
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/EndWithDetector.java46
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/KeywordsDetector.java57
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/LanguageFootprint.java27
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/recognizer/RegexDetector.java43
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/Line.java233
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/LineContextHandler.java59
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/LinesFactory.java139
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/LiteralValueHandler.java59
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/MultiLinesCommentHandler.java101
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/SingleLineCommentHandler.java63
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/Source.java128
-rw-r--r--sonar-squid/src/main/java/org/sonar/squid/text/StringArrayReader.java96
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/api/CheckMessageTest.java35
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTest.java135
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTreeDecoratorTest.java120
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/api/SourceFileTest.java52
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/api/SourceMethodTest.java34
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/indexer/SquidIndexTest.java111
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/math/MeasuresDistributionTest.java65
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/AbstractnessFormulaTest.java52
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesDensityFormulaTest.java47
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormulaTest.java38
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/DistanceFormulaTest.java49
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/InstabilityFormulaTest.java53
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/MeanAggregationFormulaTest.java54
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/MeasuresTest.java53
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormulaTest.java47
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/measures/SumAggregationFormulaTest.java54
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/recognizer/CamelCaseDetectorTest.java15
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/recognizer/ContainsDetectorTest.java15
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/recognizer/EndWithDetectorTest.java16
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/recognizer/KeywordsDetectorTest.java19
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/recognizer/RegexDetectorTest.java35
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/JavaFootprint.java44
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/LineTest.java90
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/LinesFactoryTest.java89
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/LiteralValueHandlerTest.java53
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/MultiLineCommentHandlerTest.java116
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/SingleLineCommentHandlerTest.java67
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/SourceTest.java180
-rw-r--r--sonar-squid/src/test/java/org/sonar/squid/text/StringArrayReaderTest.java184
87 files changed, 5363 insertions, 0 deletions
diff --git a/sonar-squid/pom.xml b/sonar-squid/pom.xml
new file mode 100644
index 00000000000..3f98dff47ab
--- /dev/null
+++ b/sonar-squid/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar</artifactId>
+ <version>2.3-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-squid</artifactId>
+ <packaging>jar</packaging>
+ <name>Sonar :: Squid</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-check-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-graph</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.picocontainer</groupId>
+ <artifactId>picocontainer</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>${basedir}/src/main/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>${basedir}/src/test/resources</directory>
+ </testResource>
+ </testResources>
+ </build>
+</project> \ No newline at end of file
diff --git a/sonar-squid/src/main/java/org/sonar/squid/Squid.java b/sonar-squid/src/main/java/org/sonar/squid/Squid.java
new file mode 100644
index 00000000000..25547f148c5
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/Squid.java
@@ -0,0 +1,146 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.containers.TransientPicoContainer;
+import org.sonar.graph.DirectedGraph;
+import org.sonar.graph.DirectedGraphAccessor;
+import org.sonar.squid.api.CodeScanner;
+import org.sonar.squid.api.CodeVisitor;
+import org.sonar.squid.api.Query;
+import org.sonar.squid.api.SourceCode;
+import org.sonar.squid.api.SourceCodeEdge;
+import org.sonar.squid.api.SourceCodeSearchEngine;
+import org.sonar.squid.api.SourceCodeTreeDecorator;
+import org.sonar.squid.api.SourceProject;
+import org.sonar.squid.api.SquidConfiguration;
+import org.sonar.squid.indexer.SquidIndex;
+import org.sonar.squid.measures.Metric;
+import org.sonar.squid.measures.MetricDef;
+
+public class Squid implements DirectedGraphAccessor<SourceCode, SourceCodeEdge>, SourceCodeSearchEngine {
+
+ private MutablePicoContainer pico;
+ private SourceProject project;
+ private SquidIndex squidIndex;
+ private DirectedGraph<SourceCode, SourceCodeEdge> graph = new DirectedGraph<SourceCode, SourceCodeEdge>();
+ private Set<CodeVisitor> externalCodeVisitors = new HashSet<CodeVisitor>();
+
+ public Squid(SquidConfiguration conf) {
+ pico = new TransientPicoContainer();
+ pico.addComponent(conf);
+ project = new SourceProject("Project");
+ squidIndex = new SquidIndex();
+ squidIndex.index(project);
+ pico.addComponent(squidIndex);
+ pico.addComponent(project);
+ pico.addComponent(graph);
+ }
+
+ public Squid() {
+ this(new SquidConfiguration());
+ }
+
+ public void registerVisitor(CodeVisitor visitor) {
+ externalCodeVisitors.add(visitor);
+ }
+
+ public void registerVisitor(Class<? extends CodeVisitor> visitor) {
+ addToPicocontainer(visitor);
+ externalCodeVisitors.add(pico.getComponent(visitor));
+ }
+
+ public <SCANNER extends CodeScanner> SCANNER register(Class<SCANNER> scannerClass) {
+ addToPicocontainer(scannerClass);
+ SCANNER scanner = pico.getComponent(scannerClass);
+ for (Object clazz : scanner.getVisitorClasses()) {
+ addToPicocontainer((Class) clazz);
+ scanner.accept(pico.<CodeVisitor>getComponent((Class) clazz));
+ }
+ for (CodeVisitor externalVisitor : externalCodeVisitors) {
+ scanner.accept(externalVisitor);
+ }
+ return scanner;
+ }
+
+ @Deprecated
+ public SourceProject aggregate() {
+ return decorateSourceCodeTreeWith(Metric.values());
+ }
+
+ public SourceProject decorateSourceCodeTreeWith(MetricDef... metrics) {
+ SourceCodeTreeDecorator decorator = new SourceCodeTreeDecorator(project);
+ decorator.decorateWith(metrics);
+ return project;
+ }
+
+ public SourceProject getProject() {
+ return project;
+ }
+
+ private void addToPicocontainer(Class classToExpose) {
+ if (pico.getComponent(classToExpose) == null) {
+ pico.addComponent(classToExpose);
+ }
+ }
+
+ public SourceCode search(String key) {
+ return squidIndex.search(key);
+ }
+
+ public Collection<SourceCode> search(Query... query) {
+ return squidIndex.search(query);
+ }
+
+ public SourceCodeEdge getEdge(SourceCode from, SourceCode to) {
+ return graph.getEdge(from, to);
+ }
+
+ public Collection<SourceCodeEdge> getIncomingEdges(SourceCode to) {
+ return graph.getIncomingEdges(to);
+ }
+
+ public Collection<SourceCodeEdge> getOutgoingEdges(SourceCode from) {
+ return graph.getOutgoingEdges(from);
+ }
+
+ public Set<SourceCode> getVertices() {
+ return graph.getVertices();
+ }
+
+ public List<SourceCodeEdge> getEdges(Collection<SourceCode> vertices) {
+ return graph.getEdges(vertices);
+ }
+
+ public boolean hasEdge(SourceCode from, SourceCode to) {
+ return graph.hasEdge(from, to);
+ }
+
+ public void flush() {
+ graph = null;
+ pico = null;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/AnalysisException.java b/sonar-squid/src/main/java/org/sonar/squid/api/AnalysisException.java
new file mode 100644
index 00000000000..8bb52803096
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/AnalysisException.java
@@ -0,0 +1,36 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public class AnalysisException extends RuntimeException {
+
+ public AnalysisException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ public AnalysisException(String arg0) {
+ super(arg0);
+ }
+
+ public AnalysisException(Throwable arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/CheckMessage.java b/sonar-squid/src/main/java/org/sonar/squid/api/CheckMessage.java
new file mode 100644
index 00000000000..a8ce8ed8c17
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/CheckMessage.java
@@ -0,0 +1,83 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.sonar.check.Message;
+
+public class CheckMessage implements Message {
+
+ private Integer line;
+ private SourceCode sourceCode;
+ private CodeCheck codeCheck;
+ private String defaultMessage;
+ private Object[] messageArguments;
+
+ public CheckMessage(CodeCheck rule, String message, Object... messageArguments) {
+ this.codeCheck = rule;
+ this.defaultMessage = message;
+ this.messageArguments = messageArguments;
+ }
+
+ public void setSourceCode(SourceCode sourceCode) {
+ this.sourceCode = sourceCode;
+ }
+
+ public SourceCode getSourceCode() {
+ return sourceCode;
+ }
+
+ public void setLine(int line) {
+ this.line = line;
+ }
+
+ public Integer getLine() {
+ return line;
+ }
+
+ public CodeCheck getChecker() {
+ return codeCheck;
+ }
+
+ public String getDefaultMessage() {
+ return defaultMessage;
+ }
+
+ public Object[] getMessageArguments() {
+ return messageArguments;
+ }
+
+ public String getText(Locale locale) {
+ return formatDefaultMessage();
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).append("source", sourceCode).append("check", codeCheck).append("msg", defaultMessage).append("line",
+ line).toString();
+ }
+
+ public String formatDefaultMessage() {
+ return MessageFormat.format(defaultMessage, messageArguments);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/CodeCheck.java b/sonar-squid/src/main/java/org/sonar/squid/api/CodeCheck.java
new file mode 100644
index 00000000000..ac7f2545ddb
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/CodeCheck.java
@@ -0,0 +1,26 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public interface CodeCheck extends CodeVisitor {
+
+ String getKey();
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/CodeScanner.java b/sonar-squid/src/main/java/org/sonar/squid/api/CodeScanner.java
new file mode 100644
index 00000000000..c9d1e21dbd9
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/CodeScanner.java
@@ -0,0 +1,39 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public abstract class CodeScanner<VISITOR extends CodeVisitor> {
+
+ private List<VISITOR> visitors = new ArrayList<VISITOR>();
+
+ public abstract Collection<Class<? extends VISITOR>> getVisitorClasses();
+
+ public final void accept(VISITOR visitor) {
+ visitors.add(visitor);
+ }
+
+ public List<VISITOR> getVisitors() {
+ return visitors;
+ }
+} \ No newline at end of file
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/CodeVisitor.java b/sonar-squid/src/main/java/org/sonar/squid/api/CodeVisitor.java
new file mode 100644
index 00000000000..82163bb2bac
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/CodeVisitor.java
@@ -0,0 +1,24 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public interface CodeVisitor {
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/Query.java b/sonar-squid/src/main/java/org/sonar/squid/api/Query.java
new file mode 100644
index 00000000000..56e5af24c28
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/Query.java
@@ -0,0 +1,26 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+
+public interface Query {
+
+ boolean match(SourceCode unit);
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceClass.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceClass.java
new file mode 100644
index 00000000000..20287f283f1
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceClass.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public class SourceClass extends SourceCode {
+
+ public SourceClass(String key) {
+ super(key);
+ }
+
+ public SourceClass(String key, String className) {
+ super(key, className);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceCode.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCode.java
new file mode 100644
index 00000000000..0cedaf8bc03
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCode.java
@@ -0,0 +1,275 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.sonar.squid.measures.Measurable;
+import org.sonar.squid.measures.Measures;
+import org.sonar.squid.measures.Metric;
+import org.sonar.squid.measures.MetricDef;
+
+public abstract class SourceCode implements Measurable, Comparable<SourceCode> {
+
+ private final String name;
+ private Measures measures = new Measures();
+ private final String key;
+ private int startAtLine = -1;
+ private int endAtLine = -1;
+ private SourceCode parent;
+ private SortedSet<SourceCode> children;
+ private SourceCodeIndexer indexer;
+ private Set<CheckMessage> messages;
+
+ public SourceCode(String key) {
+ this(key, null);
+ }
+
+ public SourceCode(String key, String name) {
+ this.key = key;
+ this.name = name;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public int compareTo(SourceCode resource) {
+ return key.compareTo(resource.getKey());
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public final void setSourceCodeIndexer(SourceCodeIndexer indexer) {
+ this.indexer = indexer;
+ }
+
+ private void index(SourceCode sourceCode) {
+ if (indexer != null) {
+ indexer.index(sourceCode);
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return (obj instanceof SourceCode) && key.equals(((SourceCode) obj).key);
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+
+ public boolean isType(Class<? extends SourceCode> resourceType) {
+ return this.getClass() == resourceType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getInt(MetricDef metric) {
+ return (int) getMeasure(metric);
+ }
+
+ /**
+ * @deprecated since 2.1. It's replaced by getInt(MetricDef). It's still defined for binary compatibility.
+ */
+ @Deprecated
+ public int getInt(Metric metric) {
+ return (int) getMeasure(metric);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getDouble(MetricDef metric) {
+ return getMeasure(metric);
+ }
+
+ /**
+ * @deprecated since 2.1. It's replaced by getDouble(MetricDef). It's still defined for binary compatibility.
+ */
+ @Deprecated
+ public double getDouble(Metric metric) {
+ return getMeasure(metric);
+ }
+
+ public void add(MetricDef metric, SourceCode child) {
+ add(metric, child.getMeasure(metric));
+ }
+
+ public void add(MetricDef metric, double value) {
+ setMeasure(metric, getMeasure(metric) + value);
+ }
+
+ public void addData(MetricDef metric, Object data) {
+ measures.setData(metric, data);
+ }
+
+ public Object getData(MetricDef metric) {
+ return measures.getData(metric);
+ }
+
+ /**
+ * @deprecated since 2.1. It's replaced by getData(MetricDef). It's still defined for binary compatibility.
+ */
+ public Object getData(Metric metric) {
+ return measures.getData(metric);
+ }
+
+ private double getMeasure(MetricDef metric) {
+ if (metric.isCalculatedMetric()) {
+ return metric.getCalculatedMetricFormula().calculate(this);
+ }
+ return measures.getValue(metric);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMeasure(MetricDef metric, double measure) {
+ if (metric.isCalculatedMetric()) {
+ throw new IllegalStateException("It's not allowed to set the value of a calculated metric : " + metric.getName());
+ }
+ measures.setValue(metric, measure);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMeasure(MetricDef metric, int measure) {
+ setMeasure(metric, (double) measure);
+ }
+
+ public void removeMeasure(MetricDef metric) {
+ measures.removeMeasure(metric);
+ }
+
+ public void setStartAtLine(int startAtLine) {
+ this.startAtLine = startAtLine;
+ this.endAtLine = startAtLine;
+ }
+
+ public void setEndAtLine(int endAtLine) {
+ this.endAtLine = endAtLine;
+ }
+
+ public int getStartAtLine() {
+ return startAtLine;
+ }
+
+ public int getEndAtLine() {
+ return endAtLine;
+ }
+
+ public SourceCode addChild(SourceCode sourceCode) {
+ if (children == null) {
+ children = new TreeSet<SourceCode>();
+ }
+ sourceCode.setParent(this);
+ if ( !children.contains(sourceCode)) {
+ children.add(sourceCode);
+ index(sourceCode);
+ }
+ return this;
+ }
+
+ public <SOURCECODE extends SourceCode> SOURCECODE getParent(Class<SOURCECODE> sourceCode) {
+ if (parent == null) {
+ return null;
+ }
+ if (parent.getClass().equals(sourceCode)) {
+ return (SOURCECODE) parent;
+ }
+ return parent.getParent(sourceCode);
+ }
+
+ public void log(CheckMessage message) {
+ message.setSourceCode(this);
+ getCheckMessages().add(message);
+ }
+
+ public Set<CheckMessage> getCheckMessages() {
+ if (messages == null) {
+ messages = new HashSet<CheckMessage>();
+ }
+ return messages;
+ }
+
+ public boolean hasCheckMessages() {
+ return messages != null && !messages.isEmpty();
+ }
+
+ public SourceCode getFirstChild() {
+ return !children.isEmpty() ? children.first() : null;
+ }
+
+ public SourceCode getLastChild() {
+ return !children.isEmpty() ? children.last() : null;
+ }
+
+ private void setParent(SourceCode parent) {
+ this.parent = parent;
+ }
+
+ public SourceCode getParent() {
+ return parent;
+ }
+
+ public Set<SourceCode> getChildren() {
+ return children;
+ }
+
+ public boolean hasChild(SourceCode squidUnit) {
+ if ( !hasChildren()) {
+ return false;
+ }
+ if (children.contains(squidUnit)) {
+ return true;
+ }
+ for (SourceCode child : children) {
+ if (child.hasChild(squidUnit)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected boolean hasChildren() {
+ return children != null && children.size() != 0;
+ }
+
+ public boolean hasAmongParents(SourceCode expectedParent) {
+ if (parent == null) {
+ return false;
+ }
+ return parent.equals(expectedParent) || parent.hasAmongParents(expectedParent);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdge.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdge.java
new file mode 100644
index 00000000000..37bf771e349
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdge.java
@@ -0,0 +1,139 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.sonar.graph.Edge;
+
+public class SourceCodeEdge implements Edge<SourceCode> {
+
+ private final SourceCode from;
+ private final SourceCode to;
+ private final SourceCodeEdgeUsage usage;
+ private Set<SourceCodeEdge> rootEdges;
+ private Set<SourceCode> rootFromNodes;
+ private Set<SourceCode> rootToNodes;
+ private final int hashcode;
+ private SourceCodeEdge parent;
+
+ public SourceCodeEdge(SourceCode from, SourceCode to, SourceCodeEdgeUsage link) {
+ this(from, to, link, null);
+ }
+
+ public SourceCodeEdge(SourceCode from, SourceCode to, SourceCodeEdgeUsage usage, SourceCodeEdge rootEdge) {
+ this.hashcode = from.hashCode() * 31 + to.hashCode() + usage.hashCode(); //NOSONAR even if this basic algorithm could be improved
+ this.from = from;
+ this.to = to;
+ this.usage = usage;
+ addRootEdge(rootEdge);
+ }
+
+ public SourceCode getFrom() {
+ return from;
+ }
+
+ public SourceCode getTo() {
+ return to;
+ }
+
+ public SourceCodeEdgeUsage getUsage() {
+ return usage;
+ }
+
+ private boolean noRoots() {
+ return rootEdges == null;
+ }
+
+ public boolean hasAnEdgeFromRootNode(SourceCode rootFromNode) {
+ if (noRoots()) {
+ return false;
+ }
+ return rootFromNodes.contains(rootFromNode);
+ }
+
+ public boolean hasAnEdgeToRootNode(SourceCode rootToNode) {
+ if (noRoots()) {
+ return false;
+ }
+ return rootToNodes.contains(rootToNode);
+ }
+
+ public Set<SourceCodeEdge> getRootEdges() {
+ return rootEdges;
+ }
+
+ public int getNumberOfRootFromNodes() {
+ if (noRoots()) {
+ return 0;
+ }
+ return rootFromNodes.size();
+ }
+
+ public final void addRootEdge(SourceCodeEdge rootRelationShip) {
+ if (noRoots()) {
+ rootEdges = new HashSet<SourceCodeEdge>();
+ rootFromNodes = new HashSet<SourceCode>();
+ rootToNodes = new HashSet<SourceCode>();
+ }
+ if (rootRelationShip != null) {
+ rootEdges.add(rootRelationShip);
+ rootFromNodes.add(rootRelationShip.getFrom());
+ rootToNodes.add(rootRelationShip.getTo());
+ rootRelationShip.setParent(this);
+ }
+ }
+
+ public int getWeight() {
+ if (noRoots()) {
+ return 0;
+ }
+ return rootEdges.size();
+ }
+
+ public SourceCodeEdge getParent() {
+ return parent;
+ }
+
+ public SourceCodeEdge setParent(SourceCodeEdge parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( !(obj instanceof SourceCodeEdge) || this.hashCode() != obj.hashCode()) {
+ return false;
+ }
+ SourceCodeEdge edge = (SourceCodeEdge) obj;
+ return from.equals(edge.from) && to.equals(edge.to);
+ }
+
+ @Override
+ public int hashCode() {
+ return hashcode;
+ }
+
+ @Override
+ public String toString() {
+ return "from : " + from + ", to : " + to;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdgeUsage.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdgeUsage.java
new file mode 100644
index 00000000000..9d4b311c580
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeEdgeUsage.java
@@ -0,0 +1,55 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public enum SourceCodeEdgeUsage {
+ /**
+ * Example: class A extends class B
+ */
+ EXTENDS,
+
+ /**
+ * Example: class A implements an interface B
+ */
+ IMPLEMENTS,
+
+ /**
+ * Examples:
+ * <ul>
+ * <li>method A returns an object of type B</li>
+ * <li>method A declares a parameter of type B</li>
+ * <li>method A throws an exception of type B</li>
+ * <li>method A catch an exception of type B</li>
+ * </ul>
+ */
+ USES,
+
+ CALLS_FIELD, CALLS_METHOD,
+
+ /**
+ * Example: class A declares a field of type B
+ */
+ CONTAINS,
+
+ /**
+ * Unknown type
+ */
+ NO_LINK
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeIndexer.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeIndexer.java
new file mode 100644
index 00000000000..7eb78e6e74b
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeIndexer.java
@@ -0,0 +1,25 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public interface SourceCodeIndexer {
+
+ void index(SourceCode sourceCode);
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeSearchEngine.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeSearchEngine.java
new file mode 100644
index 00000000000..f89afac0e85
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeSearchEngine.java
@@ -0,0 +1,30 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.util.Collection;
+
+
+public interface SourceCodeSearchEngine {
+
+ SourceCode search(String key);
+
+ Collection<SourceCode> search(Query... query);
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeTreeDecorator.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeTreeDecorator.java
new file mode 100644
index 00000000000..933ab70708d
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceCodeTreeDecorator.java
@@ -0,0 +1,55 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import org.sonar.squid.measures.MetricDef;
+
+public class SourceCodeTreeDecorator {
+
+ private final SourceProject project;
+
+ public SourceCodeTreeDecorator(SourceProject project) {
+ this.project = project;
+ }
+
+ public void decorateWith(MetricDef... metrics) {
+ decorateWith(project, metrics);
+ }
+
+ private void decorateWith(SourceCode sourceCode, MetricDef... metrics) {
+ if (sourceCode.hasChildren()) {
+ for (SourceCode child : sourceCode.getChildren()) {
+ decorateWith(child, metrics);
+ }
+ }
+ for (MetricDef metric : metrics) {
+ if ( !metric.aggregateIfThereIsAlreadyAValue() && sourceCode.getDouble(metric) != 0) {
+ continue;
+ }
+ if (sourceCode.hasChildren()) {
+ for (SourceCode child : sourceCode.getChildren()) {
+ if ( !metric.isCalculatedMetric() && metric.isThereAggregationFormula()) {
+ sourceCode.add(metric, child);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceFile.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceFile.java
new file mode 100644
index 00000000000..bd0cb5b52a7
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceFile.java
@@ -0,0 +1,54 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class SourceFile extends SourceCode {
+
+ private Set<Integer> noSonarTagLines = new HashSet<Integer>();
+
+ public SourceFile(String key) {
+ super(key);
+ setStartAtLine(1);
+ }
+
+ public SourceFile(String key, String fileName) {
+ super(key, fileName);
+ setStartAtLine(1);
+ }
+
+ public Set<Integer> getNoSonarTagLines() {
+ return noSonarTagLines;
+ }
+
+ public boolean hasNoSonarTagAtLine(int lineNumber) {
+ return noSonarTagLines.contains(lineNumber);
+ }
+
+ public void addNoSonarTagLines(Set<Integer> noSonarTagLines) {
+ this.noSonarTagLines.addAll(noSonarTagLines);
+ }
+
+ public void addNoSonarTagLine(int line) {
+ noSonarTagLines.add(line);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceFunction.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceFunction.java
new file mode 100644
index 00000000000..5a0805d9a62
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceFunction.java
@@ -0,0 +1,32 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public class SourceFunction extends SourceCode {
+
+ public SourceFunction(String key) {
+ super(key);
+ }
+
+ public SourceFunction(SourceFile sourceFile, String functionSignature, int startAtLine) {
+ super(sourceFile.getKey() + "#" + functionSignature, functionSignature);
+ setStartAtLine(startAtLine);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceMethod.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceMethod.java
new file mode 100644
index 00000000000..0378f655da4
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceMethod.java
@@ -0,0 +1,38 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import org.sonar.squid.measures.Metric;
+
+public class SourceMethod extends SourceCode {
+
+ public SourceMethod(String key) {
+ super(key);
+ }
+
+ public SourceMethod(SourceClass peekParentClass, String methodSignature, int startAtLine) {
+ super(peekParentClass.getKey() + "#" + methodSignature, methodSignature);
+ setStartAtLine(startAtLine);
+ }
+
+ public boolean isAccessor() {
+ return getInt(Metric.ACCESSORS) != 0;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourcePackage.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourcePackage.java
new file mode 100644
index 00000000000..e7c025eb94e
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourcePackage.java
@@ -0,0 +1,27 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public class SourcePackage extends SourceCode {
+
+ public SourcePackage(String key) {
+ super(key);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SourceProject.java b/sonar-squid/src/main/java/org/sonar/squid/api/SourceProject.java
new file mode 100644
index 00000000000..7d93421de12
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SourceProject.java
@@ -0,0 +1,28 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+public class SourceProject extends SourceCode {
+
+ public SourceProject(String key) {
+ super(key);
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/api/SquidConfiguration.java b/sonar-squid/src/main/java/org/sonar/squid/api/SquidConfiguration.java
new file mode 100644
index 00000000000..30321f81504
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/api/SquidConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.nio.charset.Charset;
+
+public class SquidConfiguration {
+
+ private Charset charset = Charset.defaultCharset();
+
+ public SquidConfiguration() {
+ }
+
+ public SquidConfiguration(Charset charset) {
+ this.charset = charset;
+ }
+
+ public Charset getCharset() {
+ return charset;
+ }
+
+} \ No newline at end of file
diff --git a/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByMeasure.java b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByMeasure.java
new file mode 100644
index 00000000000..f6b1cafec2c
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByMeasure.java
@@ -0,0 +1,65 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.indexer;
+
+import org.sonar.squid.api.Query;
+import org.sonar.squid.api.SourceCode;
+import org.sonar.squid.measures.Metric;
+import org.sonar.squid.measures.MetricDef;
+
+public class QueryByMeasure implements Query {
+
+ private final MetricDef metric;
+ private final Operator operator;
+ private final double value;
+
+ public enum Operator {
+ GREATER_THAN, EQUALS, GREATER_THAN_EQUALS, LESS_THAN, LESS_THAN_EQUALS
+ }
+
+ @Deprecated
+ public QueryByMeasure(Metric metric, Operator operator, double value) {
+ this((MetricDef)metric, operator, value);
+ }
+
+ public QueryByMeasure(MetricDef metric, Operator operator, double value) {
+ this.metric = metric;
+ this.operator = operator;
+ this.value = value;
+ }
+
+ public boolean match(SourceCode unit) {
+ switch (operator) {
+ case EQUALS:
+ return unit.getDouble(metric) == value;
+ case GREATER_THAN:
+ return unit.getDouble(metric) > value;
+ case GREATER_THAN_EQUALS:
+ return unit.getDouble(metric) >= value;
+ case LESS_THAN_EQUALS:
+ return unit.getDouble(metric) <= value;
+ case LESS_THAN:
+ return unit.getDouble(metric) < value;
+ default:
+ throw new IllegalStateException("The operator value '" + operator + "' is unknown.");
+ }
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByName.java b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByName.java
new file mode 100644
index 00000000000..fb2a424b4f0
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByName.java
@@ -0,0 +1,65 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.indexer;
+
+import org.sonar.squid.api.Query;
+import org.sonar.squid.api.SourceCode;
+
+public class QueryByName implements Query {
+
+ private final String resourceName;
+
+ public QueryByName(String resourceName) {
+ if (resourceName == null) {
+ throw new IllegalStateException("The name can't be null !");
+ }
+ this.resourceName = resourceName;
+ }
+
+ public boolean match(SourceCode unit) {
+ if(unit.getName() != null) {
+ return unit.getName().equals(resourceName);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if ( !(o instanceof QueryByName)) {
+ return false;
+ }
+
+ QueryByName that = (QueryByName) o;
+
+ if (resourceName != null ? !resourceName.equals(that.resourceName) : that.resourceName != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return resourceName.hashCode();
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByParent.java b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByParent.java
new file mode 100644
index 00000000000..a9a155084c1
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByParent.java
@@ -0,0 +1,36 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.indexer;
+
+import org.sonar.squid.api.Query;
+import org.sonar.squid.api.SourceCode;
+
+public class QueryByParent implements Query {
+
+ private final SourceCode parent;
+
+ public QueryByParent(SourceCode parent) {
+ this.parent = parent;
+ }
+
+ public boolean match(SourceCode unit) {
+ return unit.hasAmongParents(parent);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByType.java b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByType.java
new file mode 100644
index 00000000000..de52003613d
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/indexer/QueryByType.java
@@ -0,0 +1,62 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.indexer;
+
+import org.sonar.squid.api.Query;
+import org.sonar.squid.api.SourceCode;
+
+public class QueryByType implements Query {
+
+ private final Class<? extends SourceCode> resourceType;
+
+ public QueryByType(Class<? extends SourceCode> resourceType) {
+ if (resourceType == null) {
+ throw new IllegalStateException("The type of resource can't be null !");
+ }
+ this.resourceType = resourceType;
+ }
+
+ public boolean match(SourceCode unit) {
+ return unit.isType(resourceType);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof QueryByType)) {
+ return false;
+ }
+
+ QueryByType that = (QueryByType) o;
+
+ if (resourceType != null ? !resourceType.equals(that.resourceType) : that.resourceType != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return resourceType != null ? resourceType.hashCode() : 0;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/indexer/SquidIndex.java b/sonar-squid/src/main/java/org/sonar/squid/indexer/SquidIndex.java
new file mode 100644
index 00000000000..10632ad7f9e
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/indexer/SquidIndex.java
@@ -0,0 +1,66 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.indexer;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.sonar.squid.api.Query;
+import org.sonar.squid.api.SourceCode;
+import org.sonar.squid.api.SourceCodeIndexer;
+import org.sonar.squid.api.SourceCodeSearchEngine;
+
+public class SquidIndex implements SourceCodeIndexer, SourceCodeSearchEngine {
+
+ private Map<String, SourceCode> index = new TreeMap<String, SourceCode>();
+
+ public Collection<SourceCode> search(Query... query) {
+ Set<SourceCode> result = new HashSet<SourceCode>();
+ for (SourceCode unit : index.values()) {
+ if (isSquidUnitMatchQueries(unit, query)) {
+ result.add(unit);
+ }
+ }
+ return result;
+ }
+
+ private boolean isSquidUnitMatchQueries(SourceCode unit, Query... queries) {
+ boolean match;
+ for (Query query : queries) {
+ match = query.match(unit);
+ if (!match) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public SourceCode search(String key) {
+ return index.get(key);
+ }
+
+ public void index(SourceCode sourceCode) {
+ sourceCode.setSourceCodeIndexer(this);
+ index.put(sourceCode.getKey(), sourceCode);
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/math/MeasuresDistribution.java b/sonar-squid/src/main/java/org/sonar/squid/math/MeasuresDistribution.java
new file mode 100644
index 00000000000..b5b120a7e09
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/math/MeasuresDistribution.java
@@ -0,0 +1,52 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.math;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.sonar.squid.api.SourceCode;
+import org.sonar.squid.measures.MetricDef;
+
+public class MeasuresDistribution {
+
+ private final Collection<SourceCode> units;
+
+ public MeasuresDistribution(Collection<SourceCode> units) {
+ this.units = units;
+ }
+
+ public Map<Integer, Integer> distributeAccordingTo(MetricDef metric, int... thresholds) {
+ Map<Integer, Integer> result = new TreeMap<Integer, Integer>();
+ for (int threshold : thresholds) {
+ result.put(threshold, 0);
+ }
+ for (SourceCode unit : units) {
+ for (int index = thresholds.length - 1; index >= 0; index--) {
+ if (unit.getDouble(metric) >= thresholds[index]) {
+ result.put(thresholds[index], result.get(thresholds[index]) + 1);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/AbstractnessFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/AbstractnessFormula.java
new file mode 100644
index 00000000000..23c1c7377a3
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/AbstractnessFormula.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public class AbstractnessFormula implements CalculatedMetricFormula {
+
+ public double calculate(Measurable measurable) {
+ if (measurable.getDouble(Metric.CLASSES) == 0) {
+ return 0;
+ }
+ return (measurable.getDouble(Metric.ABSTRACT_CLASSES) + measurable.getDouble(Metric.INTERFACES)) / measurable.getDouble(Metric.CLASSES);
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/AggregationFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/AggregationFormula.java
new file mode 100644
index 00000000000..88b9dcb3d8c
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/AggregationFormula.java
@@ -0,0 +1,28 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import java.util.Collection;
+
+public interface AggregationFormula {
+
+ double aggregate(MetricDef metric, Collection<Measurable> measurables);
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/CalculatedMetricFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/CalculatedMetricFormula.java
new file mode 100644
index 00000000000..a4880c858d8
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/CalculatedMetricFormula.java
@@ -0,0 +1,26 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public interface CalculatedMetricFormula {
+
+ double calculate(Measurable measurable);
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesDensityFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesDensityFormula.java
new file mode 100644
index 00000000000..56b5ab333f8
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesDensityFormula.java
@@ -0,0 +1,32 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public class CommentLinesDensityFormula implements CalculatedMetricFormula {
+
+ public double calculate(Measurable measurable) {
+ if ((measurable.getDouble(Metric.LINES_OF_CODE) + measurable.getDouble(Metric.COMMENT_LINES_WITHOUT_HEADER)) != 0) {
+ return measurable.getDouble(Metric.COMMENT_LINES_WITHOUT_HEADER)
+ / (measurable.getDouble(Metric.LINES_OF_CODE) + measurable.getDouble(Metric.COMMENT_LINES_WITHOUT_HEADER));
+ }
+ return 0;
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormula.java
new file mode 100644
index 00000000000..9bf67b92981
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormula.java
@@ -0,0 +1,28 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public class CommentLinesWithoutHeaderFormula implements CalculatedMetricFormula {
+
+ public double calculate(Measurable mesurable) {
+ return mesurable.getInt(Metric.COMMENT_LINES) - mesurable.getInt(Metric.HEADER_COMMENT_LINES);
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/DistanceFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/DistanceFormula.java
new file mode 100644
index 00000000000..ea1ce094c98
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/DistanceFormula.java
@@ -0,0 +1,28 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public class DistanceFormula implements CalculatedMetricFormula {
+
+ public double calculate(Measurable measurable) {
+ return Math.abs(measurable.getDouble(Metric.ABSTRACTNESS) + measurable.getDouble(Metric.INSTABILITY) - 1);
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/InstabilityFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/InstabilityFormula.java
new file mode 100644
index 00000000000..f4b7c984a31
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/InstabilityFormula.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public class InstabilityFormula implements CalculatedMetricFormula {
+
+ public double calculate(Measurable measurable) {
+ if((measurable.getDouble(Metric.CA) + measurable.getDouble(Metric.CE)) == 0){
+ return 0;
+ }
+ return measurable.getDouble(Metric.CE) / (measurable.getDouble(Metric.CA) + measurable.getDouble(Metric.CE));
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/MeanAggregationFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/MeanAggregationFormula.java
new file mode 100644
index 00000000000..b0f6c1d40af
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/MeanAggregationFormula.java
@@ -0,0 +1,34 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import java.util.Collection;
+
+public class MeanAggregationFormula implements AggregationFormula {
+
+ public double aggregate(MetricDef metric, Collection<Measurable> measurables) {
+ if (measurables.isEmpty()) {
+ return 0;
+ }
+ SumAggregationFormula sumFormula = new SumAggregationFormula();
+ return sumFormula.aggregate(metric, measurables) / (double) measurables.size();
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/Measurable.java b/sonar-squid/src/main/java/org/sonar/squid/measures/Measurable.java
new file mode 100644
index 00000000000..c04525279d1
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/Measurable.java
@@ -0,0 +1,32 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public interface Measurable<T extends MetricDef> {
+
+ double getDouble(T metric);
+
+ int getInt(T metric);
+
+ void setMeasure(T metric, double measure);
+
+ void setMeasure(T metric, int measure);
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/Measures.java b/sonar-squid/src/main/java/org/sonar/squid/measures/Measures.java
new file mode 100644
index 00000000000..12d2765ac76
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/Measures.java
@@ -0,0 +1,92 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+public class Measures {
+
+ private Map<MetricDef, Measure> measures = new IdentityHashMap<MetricDef, Measure>();
+
+ public double getValue(MetricDef metric) {
+ Measure measure = measures.get(metric);
+ if (measure == null) {
+ return 0;
+ }
+ return measure.getValue();
+ }
+
+ public Object getData(MetricDef metric) {
+ Measure measure = measures.get(metric);
+ if (measure == null) {
+ return null;
+ }
+ return measure.getData();
+ }
+
+ public void setValue(MetricDef metric, double measure) {
+ getMeasureOrCreateIt(metric).setValue(measure);
+ }
+
+ public void setData(MetricDef metric, Object data) {
+ getMeasureOrCreateIt(metric).setData(data);
+ }
+
+ private Measure getMeasureOrCreateIt(MetricDef metric) {
+ Measure measure = measures.get(metric);
+ if (measure == null) {
+ measure = new Measure(0);
+ measures.put(metric, measure);
+ }
+ return measure;
+ }
+
+ public void removeMeasure(MetricDef metric) {
+ measures.remove(metric);
+ }
+
+ private static final class Measure {
+
+ private double value;
+ private Object data;
+
+ private Measure(double value) {
+ this.value = value;
+ }
+
+ private double getValue() {
+ return value;
+ }
+
+ private void setValue(double value) {
+ this.value = value;
+ }
+
+ private Object getData() {
+ return data;
+ }
+
+ private void setData(Object data) {
+ this.data = data;
+ }
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/Metric.java b/sonar-squid/src/main/java/org/sonar/squid/measures/Metric.java
new file mode 100644
index 00000000000..fefa8aeeeb9
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/Metric.java
@@ -0,0 +1,82 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public enum Metric implements MetricDef {
+
+ PACKAGES, CLASSES, ANONYMOUS_INNER_CLASSES, FILES, METHODS, CONSTRUCTORS, STATEMENTS, LINES(false), BLANK_LINES(false), COMMENT_LINES(
+ false), HEADER_COMMENT_LINES(false), COMMENTED_OUT_CODE_LINES(false), BRANCHES, PUBLIC_API, PUBLIC_DOC_API, ACCESSORS,
+ COMMENT_BLANK_LINES(false), LINES_OF_CODE(false), COMMENT_LINES_WITHOUT_HEADER(new CommentLinesWithoutHeaderFormula()),
+ PUBLIC_DOCUMENTED_API_DENSITY(new PublicDocumentedApiDensityFormula()), COMMENT_LINES_DENSITY(new CommentLinesDensityFormula()),
+ COMPLEXITY, INTERFACES, ABSTRACT_CLASSES, ABSTRACTNESS(new AbstractnessFormula()), CA(new NoAggregationFormula()), CE(
+ new NoAggregationFormula()), INSTABILITY(new InstabilityFormula()), DISTANCE(new DistanceFormula()), DIT(new NoAggregationFormula()),
+ RFC(new NoAggregationFormula()), NOC(new NoAggregationFormula()), LCOM4(new NoAggregationFormula()), LCOM4_BLOCKS;
+
+ private double initValue = 0;
+
+ private CalculatedMetricFormula formula = null;
+
+ private AggregationFormula aggregationFormula = new SumAggregationFormula();
+
+ private boolean aggregateIfThereIsAlreadyAValue = true;
+
+ Metric() {
+ }
+
+ Metric(boolean aggregateIfThereIsAlreadyAValue) {
+ this.aggregateIfThereIsAlreadyAValue = aggregateIfThereIsAlreadyAValue;
+ }
+
+ Metric(AggregationFormula aggregationFormula) {
+ this.aggregationFormula = aggregationFormula;
+ }
+
+ Metric(CalculatedMetricFormula formula) {
+ this.formula = formula;
+ }
+
+ public double getInitValue() {
+ return initValue;
+ }
+
+ public String getName() {
+ return name();
+ }
+
+ public boolean isCalculatedMetric() {
+ return formula != null;
+ }
+
+ public boolean aggregateIfThereIsAlreadyAValue() {
+ return aggregateIfThereIsAlreadyAValue;
+ }
+
+ public boolean isThereAggregationFormula() {
+ return !(aggregationFormula instanceof NoAggregationFormula);
+ }
+
+ public CalculatedMetricFormula getCalculatedMetricFormula() {
+ return formula;
+ }
+
+ public AggregationFormula getAggregationFormula() {
+ return aggregationFormula;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/MetricDef.java b/sonar-squid/src/main/java/org/sonar/squid/measures/MetricDef.java
new file mode 100644
index 00000000000..03746b0c9e9
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/MetricDef.java
@@ -0,0 +1,37 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public interface MetricDef {
+
+ String getName();
+
+ double getInitValue();
+
+ boolean isCalculatedMetric();
+
+ boolean aggregateIfThereIsAlreadyAValue();
+
+ boolean isThereAggregationFormula();
+
+ CalculatedMetricFormula getCalculatedMetricFormula();
+
+ AggregationFormula getAggregationFormula();
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/NoAggregationFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/NoAggregationFormula.java
new file mode 100644
index 00000000000..44609896f46
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/NoAggregationFormula.java
@@ -0,0 +1,30 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import java.util.Collection;
+
+public class NoAggregationFormula implements AggregationFormula {
+
+ public double aggregate(MetricDef metric, Collection<Measurable> measurables) {
+ return 0;
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormula.java
new file mode 100644
index 00000000000..a6ee6e906ea
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormula.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+public class PublicDocumentedApiDensityFormula implements CalculatedMetricFormula {
+
+ public double calculate(Measurable measurable) {
+ if (measurable.getDouble(Metric.PUBLIC_API) == 0) {
+ return 1;
+ }
+ return measurable.getDouble(Metric.PUBLIC_DOC_API) / measurable.getDouble(Metric.PUBLIC_API);
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/measures/SumAggregationFormula.java b/sonar-squid/src/main/java/org/sonar/squid/measures/SumAggregationFormula.java
new file mode 100644
index 00000000000..aface2e2d63
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/measures/SumAggregationFormula.java
@@ -0,0 +1,34 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import java.util.Collection;
+
+public class SumAggregationFormula implements AggregationFormula {
+
+ public double aggregate(MetricDef metric, Collection<Measurable> measurables) {
+ double aggregation = 0;
+ for (Measurable measurable : measurables) {
+ aggregation += measurable.getDouble(metric);
+ }
+ return aggregation;
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/CamelCaseDetector.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/CamelCaseDetector.java
new file mode 100644
index 00000000000..60e4c1d2027
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/CamelCaseDetector.java
@@ -0,0 +1,45 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+public class CamelCaseDetector extends Detector {
+
+ public CamelCaseDetector(double probability) {
+ super(probability);
+ }
+
+ @Override
+ public int scan(String line) {
+ char previousChar = ' ';
+ char indexChar;
+ for (int i = 0; i < line.length(); i++) {
+ indexChar = line.charAt(i);
+ if (isLowerCaseThenUpperCase(previousChar, indexChar)) {
+ return 1;
+ }
+ previousChar = indexChar;
+ }
+ return 0;
+ }
+
+ private boolean isLowerCaseThenUpperCase(char previousChar, char indexChar) {
+ return Character.getType(previousChar) == Character.LOWERCASE_LETTER && Character.getType(indexChar) == Character.UPPERCASE_LETTER;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/CodeRecognizer.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/CodeRecognizer.java
new file mode 100644
index 00000000000..7a8a1c14349
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/CodeRecognizer.java
@@ -0,0 +1,56 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CodeRecognizer {
+
+ private LanguageFootprint language;
+ private double threshold;
+
+ public CodeRecognizer(double threshold, LanguageFootprint language) {
+ this.language = language;
+ this.threshold = threshold;
+ }
+
+ public final double recognition(String line) {
+ double probability = 0;
+ for (Detector pattern : language.getDetectors()) {
+ probability = 1 - ((1 - probability) * (1 - pattern.recognition(line)));
+ }
+ return probability;
+ }
+
+ public final List<String> extractCodeLines(List<String> lines) {
+ ArrayList<String> codeLines = new ArrayList<String>();
+ for (String line : lines) {
+ if (recognition(line) >= threshold) {
+ codeLines.add(line);
+ }
+ }
+ return codeLines;
+ }
+
+ public final boolean isLineOfCode(String line) {
+ return recognition(line) - threshold > 0;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/ContainsDetector.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/ContainsDetector.java
new file mode 100644
index 00000000000..f0ac480594b
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/ContainsDetector.java
@@ -0,0 +1,45 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+
+public class ContainsDetector extends Detector {
+
+ private List<String> strs;
+
+ public ContainsDetector(double probability, String... strs) {
+ super(probability);
+ this.strs = Arrays.asList(strs);
+ }
+
+ @Override
+ public int scan(String line) {
+ String lineWithoutWhitespaces = StringUtils.deleteWhitespace(line);
+ int matchers = 0;
+ for (String str : strs) {
+ matchers += StringUtils.countMatches(lineWithoutWhitespaces, str);
+ }
+ return matchers;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/Detector.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/Detector.java
new file mode 100644
index 00000000000..7fa1083b8a1
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/Detector.java
@@ -0,0 +1,42 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+public abstract class Detector {
+
+ public final double probability;
+
+ public Detector(double probability) {
+ if (probability < 0 || probability > 1) {
+ throw new IllegalArgumentException("probability should be between [0 .. 1]");
+ }
+ this.probability = probability;
+ }
+
+ public abstract int scan(String line);
+
+ public final double recognition(String line) {
+ int matchers = scan(line);
+ if (matchers == 0) {
+ return 0;
+ }
+ return 1 - Math.pow(1 - probability, scan(line));
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/EndWithDetector.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/EndWithDetector.java
new file mode 100644
index 00000000000..066a35c2e5f
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/EndWithDetector.java
@@ -0,0 +1,46 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+public class EndWithDetector extends Detector {
+
+ private char[] endOfLines;
+
+ public EndWithDetector(double probability, char... endOfLines) {
+ super(probability);
+ this.endOfLines = endOfLines;
+ }
+
+ @Override
+ public int scan(String line) {
+ for (int index = line.length() - 1; index >= 0; index--) {
+ char character = line.charAt(index);
+ for (char endOfLine : endOfLines) {
+ if ( character == endOfLine) {
+ return 1;
+ }
+ }
+ if(!Character.isWhitespace(character) && character != '*' && character != '/'){
+ return 0;
+ }
+ }
+ return 0;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/KeywordsDetector.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/KeywordsDetector.java
new file mode 100644
index 00000000000..a4e708f8fe5
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/KeywordsDetector.java
@@ -0,0 +1,57 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+public class KeywordsDetector extends Detector {
+
+ private List<String> keywords;
+ private boolean toUpperCase = false;
+
+ public KeywordsDetector(double probability, String... keywords) {
+ super(probability);
+ this.keywords = Arrays.asList(keywords);
+ }
+
+ public KeywordsDetector(double probability, boolean toUpperCase, String... keywords) {
+ this(probability, keywords);
+ this.toUpperCase = toUpperCase;
+ }
+
+ @Override
+ public int scan(String line) {
+ int matchers = 0;
+ if (toUpperCase) {
+ line = line.toUpperCase(Locale.getDefault());
+ }
+ StringTokenizer tokenizer = new StringTokenizer(line, " \t(),{}");
+ while (tokenizer.hasMoreTokens()) {
+ String word = tokenizer.nextToken();
+ if (keywords.contains(word)) {
+ matchers++;
+ }
+ }
+ return matchers;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/LanguageFootprint.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/LanguageFootprint.java
new file mode 100644
index 00000000000..469118a57b8
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/LanguageFootprint.java
@@ -0,0 +1,27 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+import java.util.Set;
+
+public interface LanguageFootprint {
+
+ Set<Detector> getDetectors();
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/recognizer/RegexDetector.java b/sonar-squid/src/main/java/org/sonar/squid/recognizer/RegexDetector.java
new file mode 100644
index 00000000000..0ffa49303a5
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/recognizer/RegexDetector.java
@@ -0,0 +1,43 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.recognizer;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class RegexDetector extends Detector {
+
+ private Pattern regex;
+
+ public RegexDetector(String regex, double probability) {
+ super(probability);
+ this.regex = Pattern.compile(regex);
+ }
+
+ @Override
+ public int scan(String line) {
+ Matcher matcher = regex.matcher(line);
+ int matchers = 0;
+ while (matcher.find()) {
+ matchers++;
+ }
+ return matchers;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/Line.java b/sonar-squid/src/main/java/org/sonar/squid/text/Line.java
new file mode 100644
index 00000000000..ef633b4c79f
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/Line.java
@@ -0,0 +1,233 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.apache.commons.lang.StringUtils;
+import org.sonar.squid.measures.Measurable;
+import org.sonar.squid.measures.Metric;
+
+class Line implements Measurable<Metric> {
+
+ private final int lineIndex;
+ private int blankLine = 0;
+ private int line = 1;
+ private int lineOfCode = 0;
+ private int commentLine = 0;
+ private int headerCommentLine = 0;
+ private int commentBlankLine = 0;
+ private int commentedOutCodeLine = 0;
+ private String comment = null;
+ private StringBuilder stringLine;
+ private boolean isBlank;
+ private boolean isThereJavadoc;
+ private boolean isThereLicenseHeaderComment;
+ private final static String NOSONAR_TAG = "NOSONAR";
+
+ Line() {
+ this.lineIndex = 0;
+ }
+
+ Line(String stringLine) {
+ this();
+ setString(new StringBuilder(stringLine));
+ }
+
+ Line(int lineIndex, StringBuilder stringLine) {
+ this(lineIndex);
+ setString(stringLine);
+ }
+
+ Line(int lineIndex) {
+ this.lineIndex = lineIndex;
+ }
+
+ final void setString(StringBuilder stringLine) {
+ this.stringLine = stringLine;
+ isBlank = isBlankLine();
+ }
+
+ private boolean isBlankLine() {
+ for (int i = 0; i < stringLine.length(); i++) {
+ if ( !Character.isWhitespace(stringLine.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getDouble(Metric metric) {
+ return getInt(metric);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getInt(Metric metric) {
+ switch (metric) {
+ case BLANK_LINES:
+ return blankLine;
+ case LINES:
+ return line;
+ case LINES_OF_CODE:
+ return lineOfCode;
+ case COMMENT_LINES:
+ return commentLine;
+ case COMMENTED_OUT_CODE_LINES:
+ return commentedOutCodeLine;
+ case COMMENT_BLANK_LINES:
+ return commentBlankLine;
+ case HEADER_COMMENT_LINES:
+ return headerCommentLine;
+ default:
+ throw new IllegalStateException("Metric " + metric.name() + " is not available on Line object.");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMeasure(Metric metric, double measure) {
+ setMeasure(metric, (int) measure);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMeasure(Metric metric, int measure) {
+ switch (metric) {
+ case BLANK_LINES:
+ blankLine = measure;
+ break;
+ case LINES_OF_CODE:
+ lineOfCode = measure;
+ break;
+ case COMMENT_LINES:
+ commentLine = measure;
+ break;
+ case COMMENTED_OUT_CODE_LINES:
+ commentedOutCodeLine = measure;
+ break;
+ case COMMENT_BLANK_LINES:
+ commentBlankLine = measure;
+ break;
+ case HEADER_COMMENT_LINES:
+ headerCommentLine = measure;
+ break;
+ case LINES:
+ throw new IllegalStateException("Metric LINES always equals 1 on a Line and you are not permitted to change this value.");
+ default:
+ throw new IllegalStateException("Metric " + metric.name() + " is not suitable for Line object.");
+ }
+ }
+
+ void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ void setComment(String comment, boolean isJavadoc) {
+ setComment(comment);
+ this.isThereJavadoc = isJavadoc;
+ }
+
+ void setComment(String comment, boolean isJavadoc, boolean isLicenseHeader) {
+ setComment(comment, isJavadoc);
+ this.isThereLicenseHeaderComment = isLicenseHeader;
+ }
+
+ String getString() {
+ return stringLine.toString();
+ }
+
+ boolean isBlank() {
+ return !isThereComment() && isBlank;
+ }
+
+ boolean isThereCode() {
+ if ( !isBlank() && !isThereComment()) {
+ return true;
+ }
+ if (isThereComment() && isThereCodeBeforeOrAfterComment()) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isThereCodeBeforeOrAfterComment() {
+ if ( !isThereComment()) {
+ throw new IllegalStateException("You can't call this method when there isn't any comment");
+ }
+ boolean isThereCodeBeforeComment = false;
+ boolean isThereCodeAfterComment = false;
+ int commentStartIndex = stringLine.indexOf(comment);
+ int commentEndIndex = commentStartIndex + comment.length() - 1;
+ if (commentStartIndex > 0) {
+ isThereCodeBeforeComment = !StringUtils.isBlank(stringLine.substring(0, commentStartIndex - 1));
+ }
+ if (commentEndIndex > 0 && commentEndIndex != stringLine.length() - 1) {
+ isThereCodeAfterComment = !StringUtils.isBlank(stringLine.substring(commentEndIndex + 1));
+ }
+ return isThereCodeBeforeComment || isThereCodeAfterComment;
+ }
+
+ boolean isThereComment() {
+ return comment != null;
+ }
+
+ String getComment() {
+ return comment;
+ }
+
+ boolean isThereBlankComment() {
+ if (isThereComment()) {
+ for (int i = 0; i < comment.length(); i++) {
+ char character = comment.charAt(i);
+ if ( !Character.isWhitespace(character) && character != '*' && character != '/') {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ boolean isThereJavadoc() {
+ return isThereJavadoc;
+ }
+
+ boolean isThereLicenseHeaderComment() {
+ return isThereLicenseHeaderComment;
+ }
+
+ boolean isThereNoSonarTag() {
+ return isThereComment() && comment.contains(NOSONAR_TAG);
+ }
+
+ int getLineIndex() {
+ return lineIndex;
+ }
+
+ void deleteLineContent() {
+ comment = null;
+ stringLine = null;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/LineContextHandler.java b/sonar-squid/src/main/java/org/sonar/squid/text/LineContextHandler.java
new file mode 100644
index 00000000000..097478c9f85
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/LineContextHandler.java
@@ -0,0 +1,59 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+abstract class LineContextHandler {
+
+ abstract boolean matchToEnd(Line line, StringBuilder pendingLine);
+
+ abstract boolean matchWithEndOfLine(Line line, StringBuilder pendingLine);
+
+ abstract boolean matchToBegin(Line line, StringBuilder pendingLine);
+
+ static boolean matchEndOfString(StringBuilder pendingLine, String end) {
+ int pendingLineIndex = pendingLine.length() - end.length();
+ if (pendingLineIndex < 0) {
+ return false;
+ }
+ for (int endIndex = 0; endIndex < end.length(); endIndex++) {
+ char endChar = end.charAt(endIndex);
+ char pendingLineChar = pendingLine.charAt(pendingLineIndex + endIndex);
+ if (endChar != pendingLineChar) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static boolean matchEndOfString(StringBuilder pendingLine, char endChar) {
+ if (pendingLine.length() < 1) {
+ return false;
+ }
+ return pendingLine.charAt(pendingLine.length() - 1) == endChar;
+ }
+
+ static char getLastCharacter(StringBuilder pendingLine) {
+ if (pendingLine.length() < 1) {
+ throw new IllegalStateException("The pending line is empty.");
+ }
+ return pendingLine.charAt(pendingLine.length() - 1);
+ }
+
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/LinesFactory.java b/sonar-squid/src/main/java/org/sonar/squid/text/LinesFactory.java
new file mode 100644
index 00000000000..6e98de3da35
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/LinesFactory.java
@@ -0,0 +1,139 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.sonar.squid.api.AnalysisException;
+
+class LinesFactory {
+
+ private final List<Line> lines = new ArrayList<Line>();
+ private char lastReadCharacter;
+ private StringBuilder currentStringBuilder = new StringBuilder();
+ private Line currentLine;
+ private static final char LF = '\n';
+ private static final char CR = '\r';
+ private static final int EOF = -1;
+ private LineContextHandler currentHandler;
+ private LineContextHandler[] handlers;
+
+ LinesFactory(Reader reader, String... additionalSingleLineCommentFlags) {
+ List<LineContextHandler> tmpHandlers = new ArrayList<LineContextHandler>();
+ for (String additionalSingleLineCommentFlag : additionalSingleLineCommentFlags) {
+ tmpHandlers.add(new SingleLineCommentHandler(additionalSingleLineCommentFlag));
+ }
+ tmpHandlers.add(new SingleLineCommentHandler("//", "*//"));
+ tmpHandlers.add(new MultiLinesCommentHandler());
+ tmpHandlers.add(new LiteralValueHandler('\''));
+ tmpHandlers.add(new LiteralValueHandler('"'));
+ this.handlers = tmpHandlers.toArray(new LineContextHandler[tmpHandlers.size()]);
+ fillLines(new BufferedReader(reader));
+ }
+
+ private void fillLines(Reader reader) {
+ try {
+ currentLine = new Line(1);
+ int nextChar;
+ do {
+ nextChar = reader.read();
+ if (isEndOfFile(nextChar)) {
+ notifyHandlersAboutEndOfLine();
+ break;
+ }
+ lastReadCharacter = (char) nextChar;
+ if (isEndOfLine(nextChar)) {
+ popOptionalRemainingEndOfLineChar(reader);
+ createNewLine();
+ continue;
+ }
+ appendToStringBuilder(nextChar);
+ notifyHandlersAboutNewChar();
+ } while (true);
+ } catch (IOException e) {
+ throw new AnalysisException("Unable to read the source code.", e);
+ } catch (Exception e) {
+ throw new AnalysisException("A problem was encountered when analyzing line " + lines.size() + " : '"
+ + currentStringBuilder.toString() + "'", e);
+ }
+ }
+
+ private void popOptionalRemainingEndOfLineChar(Reader reader) throws IOException {
+ reader.mark(1);
+ char nextChar = (char) reader.read();
+ reader.reset();
+ if (isTechnicalCharacter(nextChar) && lastReadCharacter != nextChar) {
+ reader.read();
+ }
+ }
+
+ private void notifyHandlersAboutNewChar() {
+ if (currentHandler == null) {
+ for (LineContextHandler handler : handlers) {
+ if (handler.matchToBegin(currentLine, currentStringBuilder)) {
+ currentHandler = handler;
+ break;
+ }
+ }
+ } else if (currentHandler.matchToEnd(currentLine, currentStringBuilder)) {
+ currentHandler = null;
+ }
+ }
+
+ private void notifyHandlersAboutEndOfLine() {
+ if (currentHandler != null && currentHandler.matchWithEndOfLine(currentLine, currentStringBuilder)) {
+ currentHandler = null;
+ }
+ }
+
+ private void createNewLine() {
+ notifyHandlersAboutEndOfLine();
+ currentLine.setString(currentStringBuilder);
+ lines.add(currentLine);
+ currentLine = new Line(lines.size() + 1);
+ currentStringBuilder = new StringBuilder();
+ }
+
+ private void appendToStringBuilder(int nextChar) {
+ if (!isTechnicalCharacter(nextChar)) {
+ currentStringBuilder.append((char) nextChar);
+ }
+ }
+
+ private boolean isEndOfFile(int nextChar) {
+ return nextChar == EOF && currentStringBuilder.length() == 0 && lastReadCharacter != LF;
+ }
+
+ private boolean isEndOfLine(int nextChar) {
+ return nextChar == EOF || (char) nextChar == LF || (char) nextChar == CR;
+ }
+
+ private boolean isTechnicalCharacter(int nextChar) {
+ return nextChar == LF || nextChar == CR || nextChar == EOF;
+ }
+
+ List<Line> getLines() {
+ return lines;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/LiteralValueHandler.java b/sonar-squid/src/main/java/org/sonar/squid/text/LiteralValueHandler.java
new file mode 100644
index 00000000000..907c87827c9
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/LiteralValueHandler.java
@@ -0,0 +1,59 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+public class LiteralValueHandler extends LineContextHandler {
+
+ private final char delimiter;
+
+ public LiteralValueHandler(char delimiter) {
+ this.delimiter = delimiter;
+ }
+
+ @Override
+ boolean matchToEnd(Line line, StringBuilder pendingLine) {
+ return matchEndOfString(pendingLine, delimiter) && evenNumberOfBackSlashBeforeDelimiter(pendingLine);
+ }
+
+ private boolean evenNumberOfBackSlashBeforeDelimiter(StringBuilder pendingLine) {
+ int numberOfBackSlashChar = 0;
+ for (int index = pendingLine.length() - 2; index >= 0; index--) {
+ if (pendingLine.charAt(index) == '\\') {
+ numberOfBackSlashChar++;
+ } else {
+ break;
+ }
+ }
+ return numberOfBackSlashChar % 2 == 0;
+ }
+
+ @Override
+ boolean matchToBegin(Line line, StringBuilder pendingLine) {
+ if (matchEndOfString(pendingLine, delimiter)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ boolean matchWithEndOfLine(Line line, StringBuilder pendingLine) {
+ return true; //see http://jira.codehaus.org/browse/SONAR-1555
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/MultiLinesCommentHandler.java b/sonar-squid/src/main/java/org/sonar/squid/text/MultiLinesCommentHandler.java
new file mode 100644
index 00000000000..5aeaadd12ce
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/MultiLinesCommentHandler.java
@@ -0,0 +1,101 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+public class MultiLinesCommentHandler extends LineContextHandler {
+
+ private StringBuilder currentLineComment;
+ private boolean isFirstLineOfComment = false;
+
+ private boolean isJavadoc = false;
+ private boolean isLicenseHeader = false;
+
+ private boolean commentStarted = false;
+
+ private static final String START_COMMENT_TAG = "/*";
+ private static final String START_JAVADOC_TAG = "/**";
+ private static final String START_GWT_NATIVE_CODE_TAG = "/*-{";
+ private static final String END_COMMENT_TAG = "*/";
+
+ @Override
+ boolean matchToEnd(Line line, StringBuilder pendingLine) {
+ if ( !commentStarted) {
+ throw new IllegalStateException("Method doContextBegin(StringBuilder pendingLine) has not been called first (line = '" + pendingLine
+ + "').");
+ }
+ currentLineComment.append(getLastCharacter(pendingLine));
+ if (isJavaDoc()) {
+ isJavadoc = true;
+ }
+ if (isGwtNativeCode()) {
+ initProperties();
+ return true;
+ }
+ boolean match = matchEndOfString(pendingLine, END_COMMENT_TAG);
+ if (match && !(isFirstLineOfComment && pendingLine.indexOf(START_COMMENT_TAG) + 1 == pendingLine.indexOf(END_COMMENT_TAG))) {
+ endOfCommentLine(line);
+ initProperties();
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isGwtNativeCode() {
+ return isFirstLineOfComment && currentLineComment.length() == START_GWT_NATIVE_CODE_TAG.length()
+ && currentLineComment.toString().equals(START_GWT_NATIVE_CODE_TAG);
+ }
+
+ private boolean isJavaDoc() {
+ return isFirstLineOfComment && currentLineComment.length() == START_JAVADOC_TAG.length()
+ && currentLineComment.toString().equals(START_JAVADOC_TAG);
+ }
+
+ @Override
+ boolean matchToBegin(Line line, StringBuilder pendingLine) {
+ boolean match = matchEndOfString(pendingLine, START_COMMENT_TAG);
+ if (match) {
+ isFirstLineOfComment = true;
+ commentStarted = true;
+ currentLineComment = new StringBuilder(START_COMMENT_TAG);
+ isLicenseHeader = (line.getLineIndex() == 1);
+ }
+ return match;
+ }
+
+ @Override
+ boolean matchWithEndOfLine(Line line, StringBuilder pendingLine) {
+ endOfCommentLine(line);
+ return false;
+ }
+
+ private void endOfCommentLine(Line line) {
+ line.setComment(currentLineComment.toString(), isJavadoc, isLicenseHeader);
+ currentLineComment = new StringBuilder();
+ isFirstLineOfComment = false;
+ }
+
+ private void initProperties() {
+ commentStarted = false;
+ isJavadoc = false;
+ isLicenseHeader = false;
+ currentLineComment = new StringBuilder();
+ isFirstLineOfComment = false;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/SingleLineCommentHandler.java b/sonar-squid/src/main/java/org/sonar/squid/text/SingleLineCommentHandler.java
new file mode 100644
index 00000000000..f20861a96d8
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/SingleLineCommentHandler.java
@@ -0,0 +1,63 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+public class SingleLineCommentHandler extends LineContextHandler {
+
+ private StringBuilder comment;
+
+ private final String commentStartTag;
+ private final String commentNotStartTag;
+
+ public SingleLineCommentHandler(String commentStartTag) {
+ this(commentStartTag, null);
+ }
+
+ public SingleLineCommentHandler(String commentStartTag, String commentNotStartTag) {
+ this.commentStartTag = commentStartTag;
+ this.commentNotStartTag = commentNotStartTag;
+ }
+
+ @Override
+ boolean matchToEnd(Line line, StringBuilder pendingLine) {
+ if (comment == null) {
+ throw new IllegalStateException("Method doContextBegin(StringBuilder pendingLine) has not been called.");
+ }
+ comment.append(getLastCharacter(pendingLine));
+ return false;
+ }
+
+ @Override
+ boolean matchToBegin(Line line, StringBuilder pendingLine) {
+ boolean doContextBegin = matchEndOfString(pendingLine, commentStartTag)
+ && (commentNotStartTag == null || !matchEndOfString(pendingLine, commentNotStartTag));
+ if (doContextBegin) {
+ comment = new StringBuilder(commentStartTag);
+ }
+ return doContextBegin;
+ }
+
+ @Override
+ boolean matchWithEndOfLine(Line line, StringBuilder pendingLine) {
+ line.setComment(comment.toString());
+ comment = null;
+ return true;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/Source.java b/sonar-squid/src/main/java/org/sonar/squid/text/Source.java
new file mode 100644
index 00000000000..5087aaba331
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/Source.java
@@ -0,0 +1,128 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.sonar.squid.measures.Metric;
+import org.sonar.squid.recognizer.CodeRecognizer;
+
+public class Source {
+
+ private List<Line> lines = new ArrayList<Line>();
+ private CodeRecognizer codeRecognizer;
+ private Set<Integer> noSonarTagLines = new HashSet<Integer>();
+
+ public Source(Reader reader, CodeRecognizer codeRecognizer, String... additionalSingleLineCommentFlag) {
+ this.codeRecognizer = codeRecognizer;
+ LinesFactory linesFactory = new LinesFactory(reader, additionalSingleLineCommentFlag);
+ lines = linesFactory.getLines();
+ processLines();
+ }
+
+ public Source(String[] stringLines, CodeRecognizer codeRecognizer) {
+ this(new StringArrayReader(stringLines), codeRecognizer);
+ }
+
+ private void processLines() {
+ for (Line line : lines) {
+ computeBlankLine(line);
+ computeHeaderCommentLine(line);
+ computeCommentLine(line);
+ computeCommentBlankLine(line);
+ computeLineOfCode(line);
+ computeNoSonarTag(line);
+ line.deleteLineContent();
+ }
+ }
+
+ private void computeNoSonarTag(Line line) {
+ if (line.isThereNoSonarTag()) {
+ noSonarTagLines.add(line.getLineIndex());
+ }
+ }
+
+ private void computeLineOfCode(Line line) {
+ if (line.isThereCode()) {
+ line.setMeasure(Metric.LINES_OF_CODE, 1);
+ }
+ }
+
+ private void computeHeaderCommentLine(Line line) {
+ if (line.isThereComment() && !line.isThereBlankComment() && line.isThereLicenseHeaderComment()) {
+ line.setMeasure(Metric.HEADER_COMMENT_LINES, 1);
+ }
+ }
+
+ private void computeCommentLine(Line line) {
+ if (line.isThereComment() && !line.isThereBlankComment()) {
+ if (line.isThereJavadoc() || line.isThereLicenseHeaderComment()) {
+ line.setMeasure(Metric.COMMENT_LINES, 1);
+ return;
+ }
+
+ boolean isCommentedOutCode = codeRecognizer.isLineOfCode(line.getComment());
+ if (!isCommentedOutCode) {
+ line.setMeasure(Metric.COMMENT_LINES, 1);
+ } else {
+ line.setMeasure(Metric.COMMENTED_OUT_CODE_LINES, 1);
+ }
+ }
+ }
+
+ private void computeBlankLine(Line line) {
+ if (line.isBlank()) {
+ line.setMeasure(Metric.BLANK_LINES, 1);
+ }
+ }
+
+ private void computeCommentBlankLine(Line line) {
+ if (line.isThereBlankComment()) {
+ line.setMeasure(Metric.COMMENT_BLANK_LINES, 1);
+ }
+ }
+
+ public int getMeasure(Metric metric) {
+ return getMeasure(metric, 1, lines.size());
+ }
+
+ public int getMeasure(Metric metric, int fromLine, int toLine) {
+ if (toLine > lines.size()) {
+ throw new IllegalStateException("There are only " + lines.size() + " lines in the file and you're trying to reach line " + toLine);
+ }
+ if (fromLine < 1) {
+ throw new IllegalStateException("Line index starts from 1 and not from " + fromLine);
+ }
+
+ int measure = 0;
+ for (int index = fromLine; index < toLine + 1; index++) {
+ measure += lines.get(index - 1).getInt(metric);
+ }
+ return measure;
+ }
+
+ public Set<Integer> getNoSonarTagLines() {
+ return noSonarTagLines;
+ }
+}
diff --git a/sonar-squid/src/main/java/org/sonar/squid/text/StringArrayReader.java b/sonar-squid/src/main/java/org/sonar/squid/text/StringArrayReader.java
new file mode 100644
index 00000000000..1c923d0adc7
--- /dev/null
+++ b/sonar-squid/src/main/java/org/sonar/squid/text/StringArrayReader.java
@@ -0,0 +1,96 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+public class StringArrayReader extends Reader {
+
+ private final StringReader stringReader;
+
+ enum EndOfLineDelimiter {
+ LF, CR_PLUS_LF, CR
+ }
+
+ public StringArrayReader(String[] lines) {
+ this(lines, EndOfLineDelimiter.LF);
+ }
+
+ public StringArrayReader(String[] lines, EndOfLineDelimiter endOfLineDelimiter) {
+ if (lines == null) {
+ throw new IllegalStateException("lines object can't be null.");
+ }
+ String content = convertArrayToStringAndAppendEndOfLine(lines, endOfLineDelimiter);
+ stringReader = new StringReader(content);
+ }
+
+ private String convertArrayToStringAndAppendEndOfLine(String[] lines, EndOfLineDelimiter endOfLineDelimiter) {
+ StringBuilder content = new StringBuilder();
+ for (int i = 0; i < lines.length; i++) {
+ content.append(lines[i]);
+ if (i != (lines.length - 1)) {
+ switch (endOfLineDelimiter) {
+ case LF:
+ content.append('\n');
+ break;
+ case CR:
+ content.append('\r');
+ break;
+ case CR_PLUS_LF:
+ content.append("\r\n");
+ break;
+ }
+ }
+ }
+ return content.toString();
+ }
+
+ @Override
+ public void close() throws IOException {
+ stringReader.close();
+ }
+
+ @Override
+ public boolean ready() throws IOException {
+ return stringReader.ready();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return stringReader.markSupported();
+ }
+
+ @Override
+ public void mark(int readAheadLimit) throws IOException {
+ stringReader.mark(readAheadLimit);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ stringReader.reset();
+ }
+
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ return stringReader.read(cbuf, off, len);
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/api/CheckMessageTest.java b/sonar-squid/src/test/java/org/sonar/squid/api/CheckMessageTest.java
new file mode 100644
index 00000000000..d2f59c2ef79
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/api/CheckMessageTest.java
@@ -0,0 +1,35 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class CheckMessageTest {
+
+ @Test
+ public void testFormatDefaultMessage() {
+ CheckMessage message = new CheckMessage(null, "Value is {0,number,integer}, expected value is {1,number,integer}.", 3, 7);
+ assertThat(message.formatDefaultMessage(), is("Value is 3, expected value is 7."));
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTest.java b/sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTest.java
new file mode 100644
index 00000000000..471a6b4d82a
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTest.java
@@ -0,0 +1,135 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.squid.measures.Measurable;
+import org.sonar.squid.measures.Metric;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class SourceCodeTest {
+
+ private SourceProject prj;
+ private SourcePackage pac;
+ private SourcePackage pac2;
+ private SourceCode cla;
+ private SourceCode cla2;
+
+ @Before
+ public void before() {
+ prj = new SourceProject("dummy project");
+ pac = new SourcePackage("org.sonar");
+ pac2 = new SourcePackage("org.sonar2");
+ pac2 = new SourcePackage("org.sonar2");
+ cla = new SourceClass("org.sonar.Toto", "Toto");
+ cla2 = new SourceClass("org.sonar2.Tata", "Tata");
+ prj.addChild(pac);
+ prj.addChild(pac2);
+ pac.addChild(cla);
+ pac.addChild(cla2);
+ }
+
+ @Test
+ public void testAddChild() {
+ prj.addChild(pac);
+ assertEquals(pac.getParent(), prj);
+ assertTrue(prj.getChildren().contains(pac));
+ }
+
+ @Test
+ public void testEqualsAndHashCode() {
+ assertFalse((prj.equals(pac)));
+ assertFalse(prj.hashCode() == pac.hashCode());
+ assertFalse(prj.equals(new Object()));
+ SourceCode samePac = new SourcePackage("org.sonar");
+ assertEquals(pac, samePac);
+ assertEquals(pac.hashCode(), samePac.hashCode());
+ }
+
+ @Test
+ public void testContains() {
+ assertThat(prj.hasChild(pac), is(true));
+ assertThat(prj.hasChild(cla), is(true));
+ }
+
+ @Test
+ public void testIsType() {
+ SourcePackage pacFrom = new SourcePackage("org.from");
+ assertFalse(pacFrom.isType(SourceCode.class));
+ assertFalse(pacFrom.isType(SourceClass.class));
+ assertTrue(pacFrom.isType(SourcePackage.class));
+ }
+
+ @Test
+ public void testGetParentByType() {
+ SourcePackage pacFrom = new SourcePackage("org.from");
+ SourceFile fileFrom = new SourceFile("org.from.From.java", "From.java");
+ SourceClass classFrom = new SourceClass("org.from.From", "From");
+ pacFrom.addChild(fileFrom);
+ fileFrom.addChild(classFrom);
+ assertEquals(pacFrom, classFrom.getParent(SourcePackage.class));
+ }
+
+ @Test
+ public void testHasAmongParents() {
+ assertTrue(cla.hasAmongParents(prj));
+ assertTrue(cla.hasAmongParents(pac));
+ assertFalse(prj.hasAmongParents(cla));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void setMeasureOnCalculatedMetric() {
+ Measurable measurable = new SourceFile("org.Toto.java");
+ measurable.setMeasure(Metric.INSTABILITY, 0);
+ }
+
+ @Test
+ public void testConmputeMeasures() {
+ cla2.setMeasure(Metric.COMPLEXITY, 4);
+ cla.setMeasure(Metric.COMPLEXITY, 2);
+ cla.setMeasure(Metric.CA, 2);
+ SourceCodeTreeDecorator decorator = new SourceCodeTreeDecorator(prj);
+ decorator.decorateWith(Metric.values());
+ assertEquals(6, prj.getInt(Metric.COMPLEXITY));
+ assertEquals(0, prj.getInt(Metric.CA));
+ }
+
+ @Test
+ public void testAddData() {
+ SourceCode myFile = new SourceFile("org.sonar2.Tata.java");
+ myFile.addData(Metric.LCOM4_BLOCKS, "blocks detail");
+ assertEquals("blocks detail", myFile.getData(Metric.LCOM4_BLOCKS));
+ }
+
+ @Test
+ public void getCheckMessages() {
+ SourceCode foo = new SourceFile("Foo.java");
+ assertThat(foo.getCheckMessages().size(), is(0));
+
+ foo.log(new CheckMessage(null, "message"));
+ assertThat(foo.getCheckMessages().size(), is(1));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTreeDecoratorTest.java b/sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTreeDecoratorTest.java
new file mode 100644
index 00000000000..71f9c7073c8
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTreeDecoratorTest.java
@@ -0,0 +1,120 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import org.junit.Test;
+import org.sonar.squid.measures.Metric;
+
+import static org.junit.Assert.assertEquals;
+
+public class SourceCodeTreeDecoratorTest {
+
+ private int idCounter = 0;
+
+ @Test
+ public void addMethodMeasures() {
+ SourceCode method1 = new SourceMethod("method1");
+ method1.setMeasure(Metric.COMPLEXITY, 4);
+ method1.setMeasure(Metric.STATEMENTS, 8);
+ method1.setMeasure(Metric.METHODS, 1);
+ SourceCode method2 = new SourceMethod("method2");
+ method2.setMeasure(Metric.COMPLEXITY, 2);
+ method2.setMeasure(Metric.STATEMENTS, 3);
+ method2.setMeasure(Metric.METHODS, 1);
+ SourceCode method3 = new SourceMethod("method3");
+ method3.setMeasure(Metric.COMPLEXITY, 1);
+ method3.setMeasure(Metric.STATEMENTS, 3);
+ method3.setMeasure(Metric.METHODS, 1);
+ SourceCode class1 = new SourceClass("class1");
+ class1.addChild(method1);
+ class1.addChild(method2);
+ class1.addChild(method3);
+
+ SourceProject project = new SourceProject("project");
+ project.addChild(class1);
+ decorate(project);
+
+ assertEquals(3, class1.getInt(Metric.METHODS));
+ assertEquals(7, class1.getInt(Metric.COMPLEXITY));
+ }
+
+ private SourceCode createTestMethod(SourceCode classResource) {
+ SourceCode method = new SourceMethod("test" + idCounter++);
+ classResource.addChild(method);
+ return method;
+ }
+
+ private SourceCode createTestClass() {
+ return new SourceClass("class" + idCounter++);
+ }
+
+ private SourceCode createTestComplexityMethod(SourceCode classResource, int complexity) {
+ SourceCode method = createTestMethod(classResource);
+ method.setMeasure(Metric.COMPLEXITY, complexity);
+ return method;
+ }
+
+ @Test
+ public void classMethodComplexityDistribution() {
+ SourceCode testClass = createTestClass();
+ createTestComplexityMethod(testClass, 4);
+ createTestComplexityMethod(testClass, 2);
+ createTestComplexityMethod(testClass, 3);
+ SourceProject project = new SourceProject("project");
+ project.addChild(testClass);
+ decorate(project);
+ }
+
+ @Test
+ public void addPackageMeasures() {
+ SourceCode package1 = new SourcePackage("pack1");
+ package1.setMeasure(Metric.CLASSES, 12);
+ package1.setMeasure(Metric.METHODS, 87);
+ package1.setMeasure(Metric.COMPLEXITY, 834);
+ package1.setMeasure(Metric.LINES, 1450);
+ package1.setMeasure(Metric.PACKAGES, 1);
+ SourceCode package2 = new SourcePackage("pack2");
+ package2.setMeasure(Metric.CLASSES, 9);
+ package2.setMeasure(Metric.METHODS, 73);
+ package2.setMeasure(Metric.COMPLEXITY, 287);
+ package2.setMeasure(Metric.LINES, 893);
+ package2.setMeasure(Metric.PACKAGES, 1);
+ SourceCode package3 = new SourcePackage("pack3");
+ package3.setMeasure(Metric.CLASSES, 9);
+ package3.setMeasure(Metric.METHODS, 73);
+ package3.setMeasure(Metric.COMPLEXITY, 287);
+ package3.setMeasure(Metric.LINES, 938);
+ package3.setMeasure(Metric.PACKAGES, 1);
+ SourceProject prj1 = new SourceProject("prj1");
+ prj1.addChild(package1);
+ prj1.addChild(package2);
+ prj1.addChild(package3);
+ decorate(prj1);
+ assertEquals(3, prj1.getInt(Metric.PACKAGES));
+ assertEquals(30, prj1.getInt(Metric.CLASSES));
+ assertEquals(233, prj1.getInt(Metric.METHODS));
+ assertEquals(3281, prj1.getInt(Metric.LINES));
+ }
+
+ private void decorate(SourceProject project) {
+ SourceCodeTreeDecorator decorator = new SourceCodeTreeDecorator(project);
+ decorator.decorateWith(Metric.values());
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/api/SourceFileTest.java b/sonar-squid/src/test/java/org/sonar/squid/api/SourceFileTest.java
new file mode 100644
index 00000000000..bae9c06c464
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/api/SourceFileTest.java
@@ -0,0 +1,52 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class SourceFileTest {
+
+ @Test
+ public void testGetStartAtLine() {
+ SourceFile file = new SourceFile("com/sonarsource/Toto.java");
+ assertEquals(1, file.getStartAtLine());
+ file = new SourceFile("com/sonarsource/Toto.java", "Toto.java");
+ assertEquals(1, file.getStartAtLine());
+ }
+
+ @Test
+ public void testHasNoSon() {
+ SourceFile file = new SourceFile("com/sonarsource/Toto.java");
+ Set<Integer> noSonarTagLines = new HashSet<Integer>();
+ noSonarTagLines.add(23);
+ noSonarTagLines.add(10);
+ file.addNoSonarTagLines(noSonarTagLines);
+ assertTrue(file.hasNoSonarTagAtLine(23));
+ assertTrue(file.hasNoSonarTagAtLine(10));
+ assertFalse(file.hasNoSonarTagAtLine(11));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/api/SourceMethodTest.java b/sonar-squid/src/test/java/org/sonar/squid/api/SourceMethodTest.java
new file mode 100644
index 00000000000..bb8183cbccb
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/api/SourceMethodTest.java
@@ -0,0 +1,34 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.api;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SourceMethodTest {
+
+ @Test
+ public void testSquidMethodSquidClassString() {
+ SourceMethod squidMethod = new SourceMethod(new SourceClass("org.sonar.Squid"), "scan:23", 23);
+ assertEquals("org.sonar.Squid#scan:23", squidMethod.getKey());
+ assertEquals(23, squidMethod.getStartAtLine());
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/indexer/SquidIndexTest.java b/sonar-squid/src/test/java/org/sonar/squid/indexer/SquidIndexTest.java
new file mode 100644
index 00000000000..1d19632c9eb
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/indexer/SquidIndexTest.java
@@ -0,0 +1,111 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.indexer;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.squid.api.SourceClass;
+import org.sonar.squid.api.SourceCode;
+import org.sonar.squid.api.SourceFile;
+import org.sonar.squid.api.SourcePackage;
+import org.sonar.squid.api.SourceProject;
+import org.sonar.squid.indexer.QueryByMeasure.Operator;
+import org.sonar.squid.measures.Metric;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class SquidIndexTest {
+
+ private SquidIndex indexer;
+ private SourceProject project;
+ private SourcePackage packSquid;
+ private SourceFile fileSquid;
+ private SourceFile file2Squid;
+ private SourceCode classSquid;
+
+ @Before
+ public void setup() {
+ indexer = new SquidIndex();
+ project = new SourceProject("Squid Project");
+ indexer.index(project);
+ packSquid = new SourcePackage("org.sonar.squid");
+ project.addChild(packSquid);
+ fileSquid = new SourceFile("org.sonar.squid.Squid.java", "Squid.java");
+ packSquid.addChild(fileSquid);
+ file2Squid = new SourceFile("org.sonar.squid.SquidConfiguration.java", "SquidConfiguration.java");
+ packSquid.addChild(file2Squid);
+ classSquid = new SourceClass("org.sonar.squid.Squid", "Squid");
+ fileSquid.addChild(classSquid);
+ }
+
+ @Test
+ public void searchSingleResource() {
+ SourceCode squidClass = indexer.search("org.sonar.squid.Squid");
+ assertEquals(new SourceClass("org.sonar.squid.Squid", "Squid"), squidClass);
+ SourceCode javaNCSSClass = indexer.search("org.sonar.squid.JavaNCSS");
+ assertNull(javaNCSSClass);
+ }
+
+ @Test
+ public void searchByType() {
+ Collection<SourceCode> resources = indexer.search(new QueryByType(SourceFile.class));
+ assertEquals(2, resources.size());
+ resources = indexer.search(new QueryByType(SourceClass.class));
+ assertEquals(1, resources.size());
+ assertTrue(resources.contains(classSquid));
+ }
+
+ @Test
+ public void searchByName() {
+ Collection<SourceCode> resources = indexer.search(new QueryByName("Squid.java"));
+ assertEquals(1, resources.size());
+ assertTrue(resources.contains(fileSquid));
+ }
+
+ @Test
+ public void searchByParent() {
+ Collection<SourceCode> resources = indexer.search(new QueryByParent(packSquid));
+ assertEquals(3, resources.size());
+ }
+
+ @Test
+ public void searchByParentAndByType() {
+ Collection<SourceCode> resources = indexer.search(new QueryByParent(packSquid), new QueryByType(SourceClass.class));
+ assertEquals(1, resources.size());
+ assertTrue(resources.contains(classSquid));
+ }
+
+ @Test
+ public void searchByMeasure() {
+ fileSquid.add(Metric.COMPLEXITY, 2);
+ assertEquals(1, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.GREATER_THAN, 1)).size());
+ assertEquals(1, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.GREATER_THAN_EQUALS, 2)).size());
+ assertEquals(0, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.GREATER_THAN, 3)).size());
+ assertEquals(4, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.LESS_THAN, 1)).size());
+ assertEquals(5, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.LESS_THAN, 3)).size());
+ assertEquals(5, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.LESS_THAN_EQUALS, 2)).size());
+ assertEquals(0, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.EQUALS, 6)).size());
+ assertEquals(1, indexer.search(new QueryByMeasure(Metric.COMPLEXITY, Operator.EQUALS, 2)).size());
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/math/MeasuresDistributionTest.java b/sonar-squid/src/test/java/org/sonar/squid/math/MeasuresDistributionTest.java
new file mode 100644
index 00000000000..b18003ee3f7
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/math/MeasuresDistributionTest.java
@@ -0,0 +1,65 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.math;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.squid.api.SourceCode;
+import org.sonar.squid.api.SourceFile;
+import org.sonar.squid.measures.Metric;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class MeasuresDistributionTest {
+
+ private MeasuresDistribution distribution;
+
+ @Before
+ public void setup() {
+ SourceFile file0 = newFile("File0.java", 0);
+ SourceFile file1 = newFile("File1.java", 1);
+ SourceFile file8 = newFile("File8.java", 8);
+ SourceFile file10 = newFile("File10.java", 10);
+ SourceFile file20 = newFile("File20.java", 20);
+ SourceFile file21 = newFile("File21.java", 21);
+ SourceFile file30 = newFile("File3.java", 30);
+ distribution = new MeasuresDistribution(Arrays.<SourceCode>asList(file0, file1, file8, file10, file20, file21, file30));
+ }
+
+ private SourceFile newFile(String filename, int complexity) {
+ SourceFile file0 = new SourceFile(filename);
+ file0.setMeasure(Metric.COMPLEXITY, complexity);
+ return file0;
+ }
+
+ @Test
+ public void testComplexityDistribution() {
+ Map<Integer, Integer> intervals = distribution.distributeAccordingTo(Metric.COMPLEXITY, 1, 10, 18, 25);
+ assertEquals(4, intervals.size());
+ assertEquals(2, (int) intervals.get(1)); // between 1 included and 10 excluded
+ assertEquals(1, (int) intervals.get(10));// between 10 included and 18 excluded
+ assertEquals(2, (int) intervals.get(18));
+ assertEquals(1, (int) intervals.get(25)); // >= 25
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/AbstractnessFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/AbstractnessFormulaTest.java
new file mode 100644
index 00000000000..11515a56d3d
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/AbstractnessFormulaTest.java
@@ -0,0 +1,52 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import org.junit.Test;
+import org.sonar.squid.api.SourcePackage;
+import org.sonar.squid.measures.AbstractnessFormula;
+import org.sonar.squid.measures.Metric;
+
+import static org.junit.Assert.assertEquals;
+
+public class AbstractnessFormulaTest {
+
+ AbstractnessFormula abstractness = new AbstractnessFormula();
+ Measurable measurable = new SourcePackage("pac1");
+
+ @Test
+ public void testCalculate() {
+ measurable.setMeasure(Metric.CLASSES, 10);
+ measurable.setMeasure(Metric.INTERFACES, 1);
+ measurable.setMeasure(Metric.ABSTRACT_CLASSES, 1);
+
+ assertEquals(0.2, abstractness.calculate(measurable), 0);
+ }
+
+ @Test
+ public void testCalculateOnEmptyProject() {
+ measurable.setMeasure(Metric.CLASSES, 0);
+ measurable.setMeasure(Metric.INTERFACES, 0);
+ measurable.setMeasure(Metric.ABSTRACT_CLASSES, 0);
+
+ assertEquals(0, abstractness.calculate(measurable), 0);
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesDensityFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesDensityFormulaTest.java
new file mode 100644
index 00000000000..fb6129ee27f
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesDensityFormulaTest.java
@@ -0,0 +1,47 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import org.junit.Test;
+import org.sonar.squid.api.SourceClass;
+
+import static org.junit.Assert.*;
+
+
+public class CommentLinesDensityFormulaTest {
+
+ CommentLinesDensityFormula formula = new CommentLinesDensityFormula();
+ Measurable measurable = new SourceClass("com.Toto");
+
+ @Test
+ public void calculateDensityOnEmptyFile() {
+ measurable.setMeasure(Metric.LINES_OF_CODE, 0);
+ measurable.setMeasure(Metric.COMMENT_LINES, 0);
+ assertEquals(0, measurable.getDouble(Metric.COMMENT_LINES_DENSITY), 0.01);
+ }
+
+ @Test
+ public void calculate() {
+ measurable.setMeasure(Metric.LINES_OF_CODE, 10);
+ measurable.setMeasure(Metric.COMMENT_LINES, 10);
+ assertEquals(0.5, measurable.getDouble(Metric.COMMENT_LINES_DENSITY), 0.01);
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormulaTest.java
new file mode 100644
index 00000000000..2d505d04255
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/CommentLinesWithoutHeaderFormulaTest.java
@@ -0,0 +1,38 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import org.junit.Test;
+import org.sonar.squid.api.SourceClass;
+
+import static org.junit.Assert.assertEquals;
+
+public class CommentLinesWithoutHeaderFormulaTest {
+
+ CommentLinesWithoutHeaderFormula formula = new CommentLinesWithoutHeaderFormula();
+ Measurable measurable = new SourceClass("com.Toto");
+
+ @Test
+ public void calculateDensityOnEmptyFile() {
+ measurable.setMeasure(Metric.COMMENT_LINES, 10);
+ measurable.setMeasure(Metric.HEADER_COMMENT_LINES, 5);
+ assertEquals(5, measurable.getInt(Metric.COMMENT_LINES_WITHOUT_HEADER));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/DistanceFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/DistanceFormulaTest.java
new file mode 100644
index 00000000000..fb4bd38893a
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/DistanceFormulaTest.java
@@ -0,0 +1,49 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import org.junit.Test;
+import org.sonar.squid.api.SourcePackage;
+
+import static org.junit.Assert.assertEquals;
+
+public class DistanceFormulaTest {
+
+ DistanceFormula distance = new DistanceFormula();
+ Measurable measurable = new SourcePackage("pac1");
+
+ @Test
+ public void calculateBestDistance() {
+ measurable.setMeasure(Metric.CLASSES, 5);
+ measurable.setMeasure(Metric.INTERFACES, 5);
+ measurable.setMeasure(Metric.CA, 10);
+ measurable.setMeasure(Metric.CE, 10);
+ assertEquals(0.5, measurable.getDouble(Metric.DISTANCE), 0.01);
+ }
+
+ @Test
+ public void calculateWorstDistance() {
+ measurable.setMeasure(Metric.CLASSES, 5);
+ measurable.setMeasure(Metric.CA, 10);
+ measurable.setMeasure(Metric.CE, 0);
+ assertEquals(1, measurable.getDouble(Metric.DISTANCE), 0.01);
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/InstabilityFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/InstabilityFormulaTest.java
new file mode 100644
index 00000000000..110cb641399
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/InstabilityFormulaTest.java
@@ -0,0 +1,53 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import org.junit.Test;
+import org.sonar.squid.api.SourcePackage;
+
+import static org.junit.Assert.assertEquals;
+
+public class InstabilityFormulaTest {
+
+ InstabilityFormula distance = new InstabilityFormula();
+ Measurable measurable = new SourcePackage("pac1");
+
+ @Test
+ public void calculateBestStability() {
+ measurable.setMeasure(Metric.CA, 50);
+ measurable.setMeasure(Metric.CE, 0);
+ assertEquals(0, measurable.getDouble(Metric.INSTABILITY), 0.01);
+ }
+
+ @Test
+ public void calculateWorstStability() {
+ measurable.setMeasure(Metric.CA, 0);
+ measurable.setMeasure(Metric.CE, 10);
+ assertEquals(1, measurable.getDouble(Metric.INSTABILITY), 0.01);
+ }
+
+ @Test
+ public void calculateOnIsolatedProject() {
+ measurable.setMeasure(Metric.CA, 0);
+ measurable.setMeasure(Metric.CE, 0);
+ assertEquals(0, measurable.getDouble(Metric.INSTABILITY), 0.01);
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/MeanAggregationFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/MeanAggregationFormulaTest.java
new file mode 100644
index 00000000000..498b91bb272
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/MeanAggregationFormulaTest.java
@@ -0,0 +1,54 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.sonar.squid.api.SourceClass;
+
+
+public class MeanAggregationFormulaTest {
+
+ MeanAggregationFormula formula = new MeanAggregationFormula();
+
+ @Test
+ public void testAggregate() {
+ List<Measurable> measurables = new ArrayList<Measurable>();
+ SourceClass class1 = new SourceClass("com.My");
+ class1.setMeasure(Metric.COMPLEXITY, 2);
+ measurables.add(class1);
+ SourceClass class2 = new SourceClass("com.My");
+ class2.setMeasure(Metric.COMPLEXITY, 3);
+ measurables.add(class2);
+
+ assertEquals(2.5, formula.aggregate(Metric.COMPLEXITY, measurables), 0.01);
+ }
+
+ @Test
+ public void testAggregateEmptyCollections() {
+ List<Measurable> measurables = new ArrayList<Measurable>();
+ assertEquals(0, formula.aggregate(Metric.COMPLEXITY, measurables), 0.01);
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/MeasuresTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/MeasuresTest.java
new file mode 100644
index 00000000000..ab5b477a493
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/MeasuresTest.java
@@ -0,0 +1,53 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class MeasuresTest {
+
+ private Measures measures = new Measures();
+
+ @Test
+ public void testGetValue() {
+ assertEquals(0, measures.getValue(Metric.ACCESSORS), 0.1);
+ }
+
+ @Test
+ public void testGetData() {
+ assertNull(measures.getData(Metric.LCOM4_BLOCKS));
+ }
+
+ @Test
+ public void testSetValue() {
+ measures.setValue(Metric.ACCESSORS, 3);
+ assertEquals(3, measures.getValue(Metric.ACCESSORS), 0.1);
+ }
+
+ @Test
+ public void testSetData() {
+ measures.setData(Metric.LCOM4_BLOCKS, "blocks detail");
+ assertEquals("blocks detail", measures.getData(Metric.LCOM4_BLOCKS));
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormulaTest.java
new file mode 100644
index 00000000000..4e2af0ad764
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/PublicDocumentedApiDensityFormulaTest.java
@@ -0,0 +1,47 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import org.junit.Test;
+import org.sonar.squid.api.SourceClass;
+
+import static org.junit.Assert.*;
+
+
+public class PublicDocumentedApiDensityFormulaTest {
+
+ PublicDocumentedApiDensityFormula formula = new PublicDocumentedApiDensityFormula();
+ Measurable measurable = new SourceClass("com.Toto");
+
+ @Test
+ public void calculateWhenNoPublicApi() {
+ measurable.setMeasure(Metric.PUBLIC_API, 0);
+ measurable.setMeasure(Metric.PUBLIC_DOC_API, 0);
+ assertEquals(1, measurable.getDouble(Metric.PUBLIC_DOCUMENTED_API_DENSITY), 0.01);
+ }
+
+ @Test
+ public void calculate() {
+ measurable.setMeasure(Metric.PUBLIC_API, 10);
+ measurable.setMeasure(Metric.PUBLIC_DOC_API, 5);
+ assertEquals(0.5, measurable.getDouble(Metric.PUBLIC_DOCUMENTED_API_DENSITY), 0.01);
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/measures/SumAggregationFormulaTest.java b/sonar-squid/src/test/java/org/sonar/squid/measures/SumAggregationFormulaTest.java
new file mode 100644
index 00000000000..2c74c53ce2e
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/measures/SumAggregationFormulaTest.java
@@ -0,0 +1,54 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.measures;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.sonar.squid.api.SourceClass;
+
+
+public class SumAggregationFormulaTest {
+
+ SumAggregationFormula formula = new SumAggregationFormula();
+
+ @Test
+ public void testAggregate() {
+ List<Measurable> measurables = new ArrayList<Measurable>();
+ SourceClass class1 = new SourceClass("com.My");
+ class1.setMeasure(Metric.COMPLEXITY, 2);
+ measurables.add(class1);
+ SourceClass class2 = new SourceClass("com.My");
+ class2.setMeasure(Metric.COMPLEXITY, 3);
+ measurables.add(class2);
+
+ assertEquals(5, formula.aggregate(Metric.COMPLEXITY, measurables), 0.01);
+ }
+
+ @Test
+ public void testAggregateEmptyCollections() {
+ List<Measurable> measurables = new ArrayList<Measurable>();
+ assertEquals(0, formula.aggregate(Metric.COMPLEXITY, measurables), 0.01);
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/recognizer/CamelCaseDetectorTest.java b/sonar-squid/src/test/java/org/sonar/squid/recognizer/CamelCaseDetectorTest.java
new file mode 100644
index 00000000000..1655aa49005
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/recognizer/CamelCaseDetectorTest.java
@@ -0,0 +1,15 @@
+package org.sonar.squid.recognizer;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CamelCaseDetectorTest {
+
+ @Test
+ public void scan() {
+ CamelCaseDetector detector = new CamelCaseDetector(0.3);
+ assertEquals(1, detector.scan("isDog() or isCat()"));
+ assertEquals(0, detector.scan("String name;"));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/recognizer/ContainsDetectorTest.java b/sonar-squid/src/test/java/org/sonar/squid/recognizer/ContainsDetectorTest.java
new file mode 100644
index 00000000000..f2e25e26a35
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/recognizer/ContainsDetectorTest.java
@@ -0,0 +1,15 @@
+package org.sonar.squid.recognizer;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class ContainsDetectorTest {
+
+ @Test
+ public void scan() {
+ ContainsDetector detector = new ContainsDetector(0.3, "++", "for(");
+ assertEquals(2, detector.scan("for (int i =0; i++; i<4) {"));
+ assertEquals(0, detector.scan("String name;"));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/recognizer/EndWithDetectorTest.java b/sonar-squid/src/test/java/org/sonar/squid/recognizer/EndWithDetectorTest.java
new file mode 100644
index 00000000000..2df5831f1db
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/recognizer/EndWithDetectorTest.java
@@ -0,0 +1,16 @@
+package org.sonar.squid.recognizer;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class EndWithDetectorTest {
+
+ @Test
+ public void scan() {
+ EndWithDetector detector = new EndWithDetector(0.3, '}');
+ assertEquals(1, detector.scan(" return true; }"));
+ assertEquals(0, detector.scan("} catch(NullPointerException e) {"));
+ assertEquals(1, detector.scan("} "));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/recognizer/KeywordsDetectorTest.java b/sonar-squid/src/test/java/org/sonar/squid/recognizer/KeywordsDetectorTest.java
new file mode 100644
index 00000000000..fde4f343b6e
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/recognizer/KeywordsDetectorTest.java
@@ -0,0 +1,19 @@
+package org.sonar.squid.recognizer;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class KeywordsDetectorTest {
+
+ @Test
+ public void scan() {
+ KeywordsDetector detector = new KeywordsDetector(0.3, "public", "static");
+ assertEquals(2, detector.scan("public static void main"));
+ assertEquals(1, detector.scan("private(static} String name;"));
+ assertEquals(0, detector.scan("publicstatic"));
+ assertEquals(0, detector.scan("i++;"));
+ detector = new KeywordsDetector(0.3, true, "PUBLIC");
+ assertEquals(2, detector.scan("Public static pubLIC"));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/recognizer/RegexDetectorTest.java b/sonar-squid/src/test/java/org/sonar/squid/recognizer/RegexDetectorTest.java
new file mode 100644
index 00000000000..a032916b1be
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/recognizer/RegexDetectorTest.java
@@ -0,0 +1,35 @@
+package org.sonar.squid.recognizer;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class RegexDetectorTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNegativeProbability() {
+ new RegexDetector("toto", -1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testProbabilityHigherThan1() {
+ new RegexDetector("toto", 1.2);
+ }
+
+ @Test
+ public void testProbability() {
+ RegexDetector pattern = new RegexDetector("toto", 0.3);
+ assertEquals(0.3, pattern.recognition(" toto "), 0.01);
+ assertEquals(0, pattern.recognition("sql"), 0.01);
+ assertEquals(1 - Math.pow(0.7, 3), pattern.recognition(" toto toto toto "), 0.01);
+ }
+
+ @Test
+ public void testSeveralMatches() {
+ RegexDetector pattern = new RegexDetector("(\\S\\.\\S)", 0.3); // \S is non-whitespace character
+ assertEquals(0.0, pattern.recognition(" toto "), 0.001);
+ assertEquals(0.3, pattern.recognition("abc.def ghi jkl"), 0.001);
+ assertEquals(0.51, pattern.recognition("abc.def.ghi"), 0.001);
+ assertEquals(0.51, pattern.recognition("abc.def ghi.jkl"), 0.001);
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/JavaFootprint.java b/sonar-squid/src/test/java/org/sonar/squid/text/JavaFootprint.java
new file mode 100644
index 00000000000..dd50cdd3a4d
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/JavaFootprint.java
@@ -0,0 +1,44 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.sonar.squid.recognizer.*;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class JavaFootprint implements LanguageFootprint {
+
+ private final Set<Detector> detectors = new HashSet<Detector>();
+
+ public JavaFootprint() {
+ detectors.add(new EndWithDetector(0.95, '}', ';', '{')); // NOSONAR Magic number is suitable in that case
+ detectors.add(new KeywordsDetector(0.7, "||", "&&")); // NOSONAR
+ detectors.add(new KeywordsDetector(0.3, "public", "abstract", "class", "implements", "extends", "return","throw",// NOSONAR
+ "private", "protected", "enum", "continue", "assert", "package", "synchronized", "boolean", "this", "double", "instanceof",
+ "final", "interface", "static", "void", "long", "int", "float", "super", "true", "case:"));
+ detectors.add(new ContainsDetector(0.95, "++", "for(", "if(", "while(", "catch(", "switch(", "try{", "else{"));// NOSONAR
+ detectors.add(new CamelCaseDetector(0.5));// NOSONAR
+ }
+
+ public Set<Detector> getDetectors() {
+ return detectors;
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/LineTest.java b/sonar-squid/src/test/java/org/sonar/squid/text/LineTest.java
new file mode 100644
index 00000000000..e385d50298d
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/LineTest.java
@@ -0,0 +1,90 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.junit.Test;
+import org.sonar.squid.measures.Metric;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class LineTest {
+
+ @Test
+ public void testIsThereCode() {
+ Line line = new Line("//comment");
+ line.setComment("//comment");
+ assertFalse(line.isThereCode());
+ line.setComment(null, false);
+ assertTrue(line.isThereCode());
+ }
+
+ @Test
+ public void testIsThereComment() {
+ Line line = new Line(" //comment");
+ line.setComment("//comment");
+ assertTrue(line.isThereComment());
+ }
+
+ @Test
+ public void testIsThereBlankComment() {
+ Line line = new Line("//");
+ line.setComment("//");
+ assertTrue(line.isThereBlankComment());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testUnexpectedMetric() {
+ Line line = new Line(" //comment");
+ line.getInt(Metric.CA);
+ }
+
+ @Test
+ public void testIsBlank() {
+ Line line = new Line(" ");
+ assertTrue(line.isBlank());
+ line.setComment("");
+ assertFalse(line.isBlank());
+ }
+
+ @Test
+ public void testIsThereCodeWithBlankLinesBeforeComment() {
+ Line line = new Line(" //comment");
+ line.setComment("//comment");
+ assertFalse(line.isThereCode());
+ }
+
+ @Test
+ public void testIsThereCodeWithBlankLinesAfterComment() {
+ Line line = new Line(" //comment");
+ line.setComment("//comment");
+ assertFalse(line.isThereCode());
+ }
+
+ @Test
+ public void testIsThereNoSonarTag() {
+ Line line = new Line(" //NOSONAR");
+ line.setComment("//NOSONAR");
+ assertTrue(line.isThereNoSonarTag());
+ line.setComment(null);
+ assertFalse(line.isThereNoSonarTag());
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/LinesFactoryTest.java b/sonar-squid/src/test/java/org/sonar/squid/text/LinesFactoryTest.java
new file mode 100644
index 00000000000..130d7990862
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/LinesFactoryTest.java
@@ -0,0 +1,89 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.junit.Test;
+
+import java.io.StringReader;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class LinesFactoryTest {
+
+ @Test
+ public void getLines() {
+ LinesFactory factory = new LinesFactory(new StringReader("import java.util.*;\n\rimport java.io.*;"));
+ assertEquals(2, factory.getLines().size());
+ assertEquals("import java.util.*;", factory.getLines().get(0).getString());
+ assertEquals("import java.io.*;", factory.getLines().get(1).getString());
+ }
+
+ @Test
+ public void getLinesWithSingleLineComment() {
+ LinesFactory factory = new LinesFactory(new StringReader("import java.util.*;\n\rint a = 4; //comments\nimport java.io.*;"));
+ Line commentLine = factory.getLines().get(1);
+ assertEquals("int a = 4; //comments", commentLine.getString());
+ assertEquals("//comments", commentLine.getComment());
+ }
+
+ @Test
+ public void getLinesWithMultiLineComment() {
+ LinesFactory factory = new LinesFactory(new StringReader("import java.util.*;\n\rint a = 4; /*comments\nimport java.io.*;*/"));
+ assertEquals("/*comments", factory.getLines().get(1).getComment());
+ assertEquals("import java.io.*;*/", factory.getLines().get(2).getComment());
+ }
+
+ @Test
+ public void testEndOfLineWithLFAndCR() {
+ LinesFactory factory = new LinesFactory(new StringReader("/*\n\r\n\r\n\r*/"));
+ assertEquals("/*", factory.getLines().get(0).getComment());
+ assertEquals("*/", factory.getLines().get(3).getComment());
+ }
+
+ @Test
+ public void testEndOfLineWithLF() {
+ LinesFactory factory = new LinesFactory(new StringReader("/*\n\n\n*/"));
+ assertEquals("/*", factory.getLines().get(0).getComment());
+ assertEquals("*/", factory.getLines().get(3).getComment());
+ }
+
+ @Test
+ public void testEndOfLineWithCR() {
+ LinesFactory factory = new LinesFactory(new StringReader("/*\r\r\r*/"));
+ assertEquals("/*", factory.getLines().get(0).getComment());
+ assertEquals("*/", factory.getLines().get(3).getComment());
+ }
+
+ @Test
+ public void getLinesWithCommentInsideDoubleQuotesString() {
+ LinesFactory factory = new LinesFactory(new StringReader("String toto = \"//NOSONAR\""));
+ Line commentLine = factory.getLines().get(0);
+ assertNull(commentLine.getComment());
+ }
+
+ @Test
+ public void getLinesWithCommentInsideSingleQuoteString() {
+ LinesFactory factory = new LinesFactory(new StringReader("String toto = \'//NOSONAR\'"));
+ Line commentLine = factory.getLines().get(0);
+ assertNull(commentLine.getComment());
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/LiteralValueHandlerTest.java b/sonar-squid/src/test/java/org/sonar/squid/text/LiteralValueHandlerTest.java
new file mode 100644
index 00000000000..b91af09540b
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/LiteralValueHandlerTest.java
@@ -0,0 +1,53 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class LiteralValueHandlerTest {
+
+ @Test
+ public void matchToBegin() {
+ LiteralValueHandler handler = new LiteralValueHandler('"');
+ assertTrue(handler.matchToBegin(new Line(), new StringBuilder("toto = \"")));
+ assertFalse(handler.matchToBegin(new Line(), new StringBuilder("toto = \'")));
+ }
+
+ @Test
+ public void matchToEnd() {
+ LiteralValueHandler handler = new LiteralValueHandler('"');
+ assertTrue(handler.matchToEnd(new Line(), new StringBuilder("toto = \"lklj\"")));
+ assertFalse(handler.matchToEnd(new Line(), new StringBuilder("\\\"")));
+ assertTrue(handler.matchToEnd(new Line(), new StringBuilder("\\\\\"")));
+ assertFalse(handler.matchToEnd(new Line(), new StringBuilder("\\\\\\\"")));
+ assertTrue(handler.matchToEnd(new Line(), new StringBuilder("\\\\\\\\\"")));
+ assertFalse(handler.matchToEnd(new Line(), new StringBuilder("toto = \'")));
+ }
+
+ @Test
+ public void matchToEndOfLine() {
+ LiteralValueHandler handler = new LiteralValueHandler('"');
+ assertTrue(handler.matchWithEndOfLine(new Line(), new StringBuilder()));
+ }
+
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/MultiLineCommentHandlerTest.java b/sonar-squid/src/test/java/org/sonar/squid/text/MultiLineCommentHandlerTest.java
new file mode 100644
index 00000000000..493b9654d6c
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/MultiLineCommentHandlerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class MultiLineCommentHandlerTest {
+
+ @Test(expected = IllegalStateException.class)
+ public void illegalCallToMatchToEnd() {
+ MultiLinesCommentHandler handler = new MultiLinesCommentHandler();
+ Line line = new Line();
+ StringBuilder builder = new StringBuilder("d");
+ handler.matchToEnd(line, builder);
+ }
+
+ @Test
+ public void matchWithEndOfLine() {
+ MultiLinesCommentHandler handler = new MultiLinesCommentHandler();
+ Line line = new Line();
+ StringBuilder builder = new StringBuilder("import java.util.*; /*");
+ assertTrue(handler.matchToBegin(line, builder));
+ builder.append('N');
+ assertFalse(handler.matchToEnd(line, builder));
+ builder.append('O');
+ assertFalse(handler.matchToEnd(line, builder));
+ assertFalse(handler.matchWithEndOfLine(line, builder));
+ assertEquals("/*NO", line.getComment());
+ builder.append('*');
+ assertFalse(handler.matchToEnd(line, builder));
+ builder.append('/');
+ assertTrue(handler.matchToEnd(line, builder));
+ assertEquals("*/", line.getComment());
+ }
+
+ @Test
+ public void testHeaderLicenseComment() {
+ MultiLinesCommentHandler handler = new MultiLinesCommentHandler();
+ Line line = new Line(1);
+ StringBuilder builder = new StringBuilder("/*");
+ assertTrue(handler.matchToBegin(line, builder));
+ assertFalse(handler.matchWithEndOfLine(line, builder));
+ assertTrue(line.isThereLicenseHeaderComment());
+
+ line = new Line(2);
+ builder = new StringBuilder("/*");
+ assertTrue(handler.matchToBegin(line, builder));
+ assertFalse(handler.matchWithEndOfLine(line, builder));
+ assertFalse(line.isThereLicenseHeaderComment());
+ }
+
+ @Test
+ public void testJavaDocComment() {
+ MultiLinesCommentHandler handler = new MultiLinesCommentHandler();
+ Line line = new Line(1);
+ StringBuilder builder = new StringBuilder("/*");
+ assertTrue(handler.matchToBegin(line, builder));
+ builder.append('*');
+ assertFalse(handler.matchToEnd(line, builder));
+ assertFalse(handler.matchWithEndOfLine(line, builder));
+ assertTrue(line.isThereJavadoc());
+
+ handler = new MultiLinesCommentHandler();
+ line = new Line(1);
+ builder = new StringBuilder("/*");
+ assertTrue(handler.matchToBegin(line, builder));
+ assertFalse(handler.matchWithEndOfLine(line, builder));
+ assertFalse(line.isThereJavadoc());
+ }
+
+ @Test
+ public void matchToBegin() {
+ MultiLinesCommentHandler handler = new MultiLinesCommentHandler();
+ assertFalse(handler.matchToBegin(new Line(), new StringBuilder("import java.util.*;")));
+ assertFalse(handler.matchToBegin(new Line(), new StringBuilder("")));
+ assertTrue(handler.matchToBegin(new Line(), new StringBuilder("import java.util.*; /*")));
+ }
+
+ @Test
+ public void testBeginEndCommentWithOnly3Chars() {
+ MultiLinesCommentHandler handler = new MultiLinesCommentHandler();
+ Line line = new Line(1);
+ StringBuilder builder = new StringBuilder("/*");
+ assertTrue(handler.matchToBegin(line, builder));
+ builder = new StringBuilder("/*/");
+ assertFalse(handler.matchToEnd(line, builder));
+
+ handler = new MultiLinesCommentHandler();
+ line = new Line(1);
+ builder = new StringBuilder("/*");
+ assertTrue(handler.matchToBegin(line, builder));
+ builder = new StringBuilder("/**/");
+ assertTrue(handler.matchToEnd(line, builder));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/SingleLineCommentHandlerTest.java b/sonar-squid/src/test/java/org/sonar/squid/text/SingleLineCommentHandlerTest.java
new file mode 100644
index 00000000000..70961a3e625
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/SingleLineCommentHandlerTest.java
@@ -0,0 +1,67 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class SingleLineCommentHandlerTest {
+
+ @Test(expected = IllegalStateException.class)
+ public void illegalCallToMatchToEnd() {
+ SingleLineCommentHandler handler = new SingleLineCommentHandler("//");
+ Line line = new Line();
+ StringBuilder builder = new StringBuilder("d");
+ handler.matchToEnd(line, builder);
+ }
+
+ @Test
+ public void matchWithEndOfLine() {
+ SingleLineCommentHandler handler = new SingleLineCommentHandler("//");
+ Line line = new Line();
+ StringBuilder builder = new StringBuilder("import java.util.*; //");
+ assertTrue(handler.matchToBegin(line, builder));
+ builder.append('N');
+ assertFalse(handler.matchToEnd(line, builder));
+ builder.append('O');
+ assertFalse(handler.matchToEnd(line, builder));
+ assertTrue(handler.matchWithEndOfLine(line, builder));
+ assertEquals("//NO", line.getComment());
+ }
+
+ @Test
+ public void matchToBegin() {
+ SingleLineCommentHandler handler = new SingleLineCommentHandler("//", "*//");
+ assertFalse(handler.matchToBegin(new Line(), new StringBuilder("import java.util.*;")));
+ assertFalse(handler.matchToBegin(new Line(), new StringBuilder("")));
+ assertTrue(handler.matchToBegin(new Line(), new StringBuilder("import java.util.*; //")));
+ assertFalse(handler.matchToBegin(new Line(), new StringBuilder("/*import java.util.*; *//")));
+ }
+
+ @Test
+ public void matchToBeginWithDoubleDash() {
+ SingleLineCommentHandler handler = new SingleLineCommentHandler("--");
+ assertFalse(handler.matchToBegin(new Line(), new StringBuilder("//")));
+ assertTrue(handler.matchToBegin(new Line(), new StringBuilder("--")));
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/SourceTest.java b/sonar-squid/src/test/java/org/sonar/squid/text/SourceTest.java
new file mode 100644
index 00000000000..73d96313f37
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/SourceTest.java
@@ -0,0 +1,180 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.junit.Test;
+import org.sonar.squid.measures.Metric;
+import org.sonar.squid.recognizer.CodeRecognizer;
+
+import java.io.StringReader;
+
+import static org.junit.Assert.assertEquals;
+
+public class SourceTest {
+
+ private CodeRecognizer codeRecognizer = new CodeRecognizer(0.91, new JavaFootprint());
+
+ @Test
+ public void testGetLines() {
+ String[] lines = { "", "int i = 0;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(2, source.getMeasure(Metric.LINES));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testGetIllegalMetric() {
+ String[] lines = { "", "int i = 0;" };
+ Source source = new Source(lines, codeRecognizer);
+ source.getMeasure(Metric.COMPLEXITY);
+ }
+
+ @Test
+ public void testGetBlankLines() {
+ String[] lines = { "package toto;", " " };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(1, source.getMeasure(Metric.BLANK_LINES));
+ }
+
+ @Test
+ public void testGetCppCommentLines() {
+ String[] lines = { "package toto;", "//this is a comment", "int i = 4; //new comment" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(2, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(1, source.getMeasure(Metric.COMMENT_LINES, 2, 2));
+ assertEquals(2, source.getMeasure(Metric.LINES_OF_CODE));
+ }
+
+ @Test
+ public void testGetCCommentLines() {
+ String[] lines = { "package toto;", " int a = 4; /*this is a comment", "new line of comment", "end of comment */ int b = 4;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(3, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(1, source.getMeasure(Metric.COMMENT_LINES, 2, 2));
+ assertEquals(3, source.getMeasure(Metric.LINES_OF_CODE));
+ }
+
+ @Test
+ public void testGetAdjacentCCommentBlocks() {
+ String[] lines = { "/*first comment*//*second ", " * + \"Ver.", "comment*/" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(3, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(3, source.getMeasure(Metric.LINES));
+ }
+
+ @Test
+ public void testGetLinesOfCode() {
+ String[] lines = { "package toto;", " ", "import java.util.*;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(2, source.getMeasure(Metric.LINES_OF_CODE));
+ assertEquals(0, source.getMeasure(Metric.LINES_OF_CODE, 2, 2));
+ }
+
+ @Test
+ public void testGetCommentedCodeOutLines() {
+ String[] lines = { "", "/*package toto;", "}*/", " ", "import java.util.*;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(1, source.getMeasure(Metric.LINES_OF_CODE));
+ assertEquals(0, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(2, source.getMeasure(Metric.COMMENTED_OUT_CODE_LINES));
+ }
+
+ @Test
+ public void testBlankLinesAfterEndOfComment() {
+ String[] lines = { "/*Comment*/ " };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(0, source.getMeasure(Metric.LINES_OF_CODE));
+ assertEquals(1, source.getMeasure(Metric.COMMENT_LINES));
+ }
+
+ @Test
+ public void testGetCommentedCodeOutLinesIntoJavadoc() {
+ String[] lines = { "/**package toto;", "}*/", " ", "import java.util.*;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(1, source.getMeasure(Metric.LINES_OF_CODE));
+ assertEquals(2, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(0, source.getMeasure(Metric.COMMENTED_OUT_CODE_LINES));
+ }
+
+ @Test
+ public void testGetBlankCommentLines() {
+ String[] lines = { "/**", "*/", "import java.util.*;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(3, source.getMeasure(Metric.LINES));
+ assertEquals(1, source.getMeasure(Metric.LINES_OF_CODE));
+ assertEquals(0, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(2, source.getMeasure(Metric.COMMENT_BLANK_LINES));
+ }
+
+ @Test
+ public void testGetNoSonarTagLines() {
+ String[] lines = { "import java.util.*;", "//NOSONAR comment", };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(1, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(1, source.getNoSonarTagLines().size());
+ }
+
+ @Test
+ public void testGetBlankLinesFromTo() {
+ String[] lines = { "package toto;", "", "import java.util.*", " " };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(1, source.getMeasure(Metric.BLANK_LINES, 1, 3));
+ assertEquals(1, source.getMeasure(Metric.BLANK_LINES, 3, 4));
+ assertEquals(2, source.getMeasure(Metric.BLANK_LINES, 1, 4));
+ }
+
+ @Test
+ public void endWithEmptyLine() {
+ String[] lines = { "package toto;", "" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(1, source.getMeasure(Metric.BLANK_LINES));
+ assertEquals(2, source.getMeasure(Metric.LINES));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testGetBlankLinesFromToWithOutOfBoundIndex() {
+ String[] lines = { "package toto;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(1, source.getMeasure(Metric.BLANK_LINES, 1, 3));
+ }
+
+ @Test
+ public void testConstructorWithReader() {
+ Source source = new Source(new StringReader("package toto; \nimport java.util.*;"), codeRecognizer);
+ assertEquals(2, source.getMeasure(Metric.LINES));
+ assertEquals(2, source.getMeasure(Metric.LINES_OF_CODE));
+ }
+
+ @Test
+ public void nativeGWTCodeRecognition() {
+ String[] lines = { "/*-{", "// JavaScript code", "return this.nextSibling;", "}-*/;" };
+ Source source = new Source(lines, codeRecognizer);
+ assertEquals(4, source.getMeasure(Metric.LINES));
+ assertEquals(3, source.getMeasure(Metric.LINES_OF_CODE));
+ assertEquals(1, source.getMeasure(Metric.COMMENT_LINES));
+ }
+
+ @Test
+ public void testSingleLineCommentWithDoubleDash() {
+ String[] lines = { "import java.util.*;", "--NOSONAR", };
+ Source source = new Source(new StringArrayReader(lines), codeRecognizer, "--");
+ assertEquals(1, source.getMeasure(Metric.COMMENT_LINES));
+ assertEquals(1, source.getNoSonarTagLines().size());
+ }
+}
diff --git a/sonar-squid/src/test/java/org/sonar/squid/text/StringArrayReaderTest.java b/sonar-squid/src/test/java/org/sonar/squid/text/StringArrayReaderTest.java
new file mode 100644
index 00000000000..b07d05accf6
--- /dev/null
+++ b/sonar-squid/src/test/java/org/sonar/squid/text/StringArrayReaderTest.java
@@ -0,0 +1,184 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.squid.text;
+
+import org.junit.Test;
+import org.sonar.squid.text.StringArrayReader.EndOfLineDelimiter;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class StringArrayReaderTest {
+
+ @Test
+ public void read() throws IOException {
+ String[] lines = { "import java.util.*;", "//NOSONAR comment", };
+ StringArrayReader reader = new StringArrayReader(lines);
+ assertEquals('i', reader.read());
+ assertEquals('m', reader.read());
+ }
+
+ @Test
+ public void testLFEndOfLineDelimiter() throws IOException {
+ String[] lines = { ";", ";", };
+ StringArrayReader reader = new StringArrayReader(lines, EndOfLineDelimiter.LF);
+ assertEquals(';', reader.read());
+ assertEquals('\n', reader.read());
+ assertEquals(';', reader.read());
+ }
+
+ @Test
+ public void testCREndOfLineDelimiter() throws IOException {
+ String[] lines = { ";", ";", };
+ StringArrayReader reader = new StringArrayReader(lines, EndOfLineDelimiter.CR);
+ assertEquals(';', reader.read());
+ assertEquals('\r', reader.read());
+ assertEquals(';', reader.read());
+ }
+
+ @Test
+ public void testCRPlusLFEndOfLineDelimiter() throws IOException {
+ String[] lines = { ";", ";", };
+ StringArrayReader reader = new StringArrayReader(lines, EndOfLineDelimiter.CR_PLUS_LF);
+ assertEquals(';', reader.read());
+ assertEquals('\r', reader.read());
+ assertEquals('\n', reader.read());
+ assertEquals(';', reader.read());
+ }
+
+ @Test
+ public void ready() throws IOException {
+ String[] lines = { ";", "//NOSONAR", };
+ StringArrayReader reader = new StringArrayReader(lines);
+ assertTrue(reader.ready());
+ }
+
+ @Test
+ public void markSupported() throws IOException {
+ String[] lines = {};
+ StringArrayReader reader = new StringArrayReader(lines);
+ assertTrue(reader.markSupported());
+ }
+
+ @Test
+ public void mark() throws IOException {
+ String[] lines = { ";", "//NOSONAR", };
+ StringArrayReader reader = new StringArrayReader(lines);
+ reader.read(new char[4], 0, 4);
+ reader.mark(4);
+ reader.read(new char[2], 0, 2);
+ reader.reset();
+ assertEquals('N', reader.read());
+ assertEquals('O', reader.read());
+ }
+
+ @Test(expected = IOException.class)
+ public void close() throws IOException {
+ String[] lines = { ";", "//NOSONAR", };
+ StringArrayReader reader = new StringArrayReader(lines);
+ assertTrue(reader.ready());
+ reader.close();
+ reader.ready();
+ }
+
+ @Test
+ public void readEndOfArray() throws IOException {
+ String[] lines = { ";" };
+ StringArrayReader reader = new StringArrayReader(lines);
+ assertEquals(';', reader.read());
+ assertEquals(-1, reader.read());
+ }
+
+ @Test
+ public void readMultipleCharacters() throws IOException {
+ String[] lines = { ";", "//NOSONAR", };
+ StringArrayReader reader = new StringArrayReader(lines);
+ char[] chars = new char[4];
+ assertEquals(4, reader.read(chars, 0, 4));
+ assertEquals(";\n//", new String(chars));
+ }
+
+ @Test
+ public void readMultipleCharactersTillEndOfArray() throws IOException {
+ String[] lines = { ";", "//NOSONAR", };
+ StringArrayReader reader = new StringArrayReader(lines);
+ char[] chars = new char[11];
+ assertEquals(11, reader.read(chars, 0, 11));
+ assertEquals(";\n//NOSONAR", new String(chars));
+ }
+
+ @Test
+ public void readEmptyArray() throws IOException {
+ String[] lines = {};
+ StringArrayReader reader = new StringArrayReader(lines);
+ char[] cbuf = new char[10000];
+ assertEquals(-1, reader.read(cbuf, 0, 10000));
+ }
+
+ @Test
+ public void readMultipleCharactersWithEmptyLineAtEnd() throws IOException {
+ String[] lines = { ";", "//NOSONAR", "", "" };
+ StringArrayReader reader = new StringArrayReader(lines);
+ char[] cbuf = new char[10000];
+ assertEquals(13, reader.read(cbuf, 0, 10000));
+ assertEquals(";\n//NOSONAR\n\n", new String(cbuf, 0, 13));
+ }
+
+ @Test
+ public void readOneCharacter() throws IOException {
+ String[] lines = { ";", "//NOSONAR" };
+ StringArrayReader reader = new StringArrayReader(lines);
+ char[] chars = new char[1];
+ assertEquals(1, reader.read(chars, 0, 1));
+ assertEquals(";", new String(chars));
+ }
+
+ @Test
+ public void readBlankLines() throws IOException {
+ String[] lines = { "", "", "" };
+ StringArrayReader reader = new StringArrayReader(lines);
+ assertEquals('\n', reader.read());
+ assertEquals('\n', reader.read());
+ assertEquals(-1, reader.read());
+ }
+
+ @Test
+ public void skip() throws IOException {
+ String[] lines = { "//NOSONAR", };
+ StringArrayReader reader = new StringArrayReader(lines);
+ reader.skip(2);
+ assertEquals('N', reader.read());
+ }
+
+ @Test
+ public void readEOF() throws IOException {
+ String[] emptyLines = {};
+ StringArrayReader reader = new StringArrayReader(emptyLines);
+ assertEquals(-1, reader.read());
+
+ String[] lines = { "a" };
+ reader = new StringArrayReader(lines);
+ assertEquals('a', reader.read());
+ assertEquals(-1, reader.read());
+ }
+
+}