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/src/main/java/org/sonar | |
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/src/main/java/org/sonar')
57 files changed, 3369 insertions, 0 deletions
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); + } +} |