diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
commit | aeadc1f9129274949daaa57738c7c4550bdfbc7b (patch) | |
tree | 08dadf5ef7474fc41d1d48f74648f1ba8b55f34d /sonar-squid | |
download | sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.tar.gz sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.zip |
SONAR-236 remove deprecated code from checkstyle plugin + display default value of rule parameters in Q profile console
Diffstat (limited to 'sonar-squid')
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()); + } + +} |