diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2015-04-22 22:07:54 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2015-04-22 22:18:07 +0200 |
commit | c96993d22c7b1a41b4c0152985e8193496cdaaae (patch) | |
tree | 43a995216518361b8795b2fe8db358753dfd966c /sonar-plugin-api/src/main | |
parent | c8d6f37f0f6ff1bc7c6107350e4954bda086a14d (diff) | |
download | sonarqube-c96993d22c7b1a41b4c0152985e8193496cdaaae.tar.gz sonarqube-c96993d22c7b1a41b4c0152985e8193496cdaaae.zip |
SONAR-6200 New Sensor API to report UT/IT/Overall coverage
Diffstat (limited to 'sonar-plugin-api/src/main')
11 files changed, 401 insertions, 6 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index 834325d7792..187c784ff00 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -24,6 +24,7 @@ import org.sonar.api.batch.AnalysisMode; import org.sonar.api.batch.CpdMapping; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.batch.sensor.coverage.NewCoverage; import org.sonar.api.batch.sensor.dependency.NewDependency; import org.sonar.api.batch.sensor.duplication.NewDuplication; import org.sonar.api.batch.sensor.highlighting.NewHighlighting; @@ -99,6 +100,12 @@ public interface SensorContext { // ------------ TESTS ------------ + /** + * Builder to define coverage in a file. + * Don't forget to call {@link NewDuplication#save()}. + */ + NewCoverage newCoverage(); + // TODO // ------------ DEPENDENCIES ------------ diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/CoverageType.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/CoverageType.java new file mode 100644 index 00000000000..fa4fcf9b0c7 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/CoverageType.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.coverage; + +import com.google.common.annotations.Beta; +import org.sonar.api.measures.Metric; + +import static org.sonar.api.measures.CoreMetrics.*; + +/** + * Different coverage categories. + * @since 5.2 + */ +@Beta +public enum CoverageType { + + UNIT(LINES_TO_COVER, UNCOVERED_LINES, COVERAGE_LINE_HITS_DATA, CONDITIONS_TO_COVER, UNCOVERED_CONDITIONS, COVERED_CONDITIONS_BY_LINE, CONDITIONS_BY_LINE), + IT(IT_LINES_TO_COVER, IT_UNCOVERED_LINES, IT_COVERAGE_LINE_HITS_DATA, IT_CONDITIONS_TO_COVER, IT_UNCOVERED_CONDITIONS, IT_COVERED_CONDITIONS_BY_LINE, IT_CONDITIONS_BY_LINE), + OVERALL(OVERALL_LINES_TO_COVER, OVERALL_UNCOVERED_LINES, OVERALL_COVERAGE_LINE_HITS_DATA, OVERALL_CONDITIONS_TO_COVER, OVERALL_UNCOVERED_CONDITIONS, + OVERALL_COVERED_CONDITIONS_BY_LINE, OVERALL_CONDITIONS_BY_LINE); + + private final Metric linesToCover; + private final Metric uncoveredLines; + private final Metric lineHitsData; + private final Metric conditionsToCover; + private final Metric uncoveredConditions; + private final Metric coveredConditionsByLine; + private final Metric conditionsByLine; + + private CoverageType(Metric linesToCover, Metric uncoveredLines, Metric lineHitsData, Metric conditionsToCover, Metric uncoveredConditions, Metric coveredConditionsByLine, + Metric conditionsByLine) { + this.linesToCover = linesToCover; + this.uncoveredLines = uncoveredLines; + this.lineHitsData = lineHitsData; + this.conditionsToCover = conditionsToCover; + this.uncoveredConditions = uncoveredConditions; + this.coveredConditionsByLine = coveredConditionsByLine; + this.conditionsByLine = conditionsByLine; + } + + public Metric linesToCover() { + return linesToCover; + } + + public Metric uncoveredLines() { + return uncoveredLines; + } + + public Metric lineHitsData() { + return lineHitsData; + } + + public Metric conditionsToCover() { + return conditionsToCover; + } + + public Metric uncoveredConditions() { + return uncoveredConditions; + } + + public Metric coveredConditionsByLine() { + return coveredConditionsByLine; + } + + public Metric conditionsByLine() { + return conditionsByLine; + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/NewCoverage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/NewCoverage.java new file mode 100644 index 00000000000..461a7865861 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/NewCoverage.java @@ -0,0 +1,58 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.coverage; + +import com.google.common.annotations.Beta; +import org.sonar.api.batch.fs.InputFile; + +/** + * This builder is used to define code coverage by tests of a given type (UT/IT/Overall) on files. + * @since 5.2 + */ +@Beta +public interface NewCoverage { + + /** + * The covered file. + */ + NewCoverage onFile(InputFile inputFile); + + NewCoverage ofType(CoverageType type); + + /** + * Call this method as many time as needed to report coverage hits per line. This method should only be called for executable lines. + * @param line Line number (starts at 1). + * @param hits Number of time the line was hit. + */ + NewCoverage lineHits(int line, int hits); + + /** + * Call this method as many time as needed to report coverage of conditions. + * @param line Line number (starts at 1). + * @param conditions Number of conditions on this line (should be greater than 1). + * @param coveredConditions Number of covered conditions. + */ + NewCoverage conditions(int line, int conditions, int coveredConditions); + + /** + * Call this method only once when your are done with defining coverage of the file. + */ + void save(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/internal/DefaultCoverage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/internal/DefaultCoverage.java new file mode 100644 index 00000000000..ff0e6aac38a --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/internal/DefaultCoverage.java @@ -0,0 +1,132 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.coverage.internal; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.coverage.CoverageType; +import org.sonar.api.batch.sensor.coverage.NewCoverage; +import org.sonar.api.batch.sensor.internal.DefaultStorable; +import org.sonar.api.batch.sensor.internal.SensorStorage; + +import javax.annotation.Nullable; + +import java.util.Collections; +import java.util.SortedMap; + +public class DefaultCoverage extends DefaultStorable implements NewCoverage { + + private DefaultInputFile inputFile; + private CoverageType type; + private int totalCoveredLines = 0, totalConditions = 0, totalCoveredConditions = 0; + private SortedMap<Integer, Integer> hitsByLine = Maps.newTreeMap(); + private SortedMap<Integer, Integer> conditionsByLine = Maps.newTreeMap(); + private SortedMap<Integer, Integer> coveredConditionsByLine = Maps.newTreeMap(); + + public DefaultCoverage() { + super(); + } + + public DefaultCoverage(@Nullable SensorStorage storage) { + super(storage); + } + + @Override + public DefaultCoverage onFile(InputFile inputFile) { + Preconditions.checkNotNull(inputFile, "file can't be null"); + this.inputFile = (DefaultInputFile) inputFile; + return this; + } + + public InputFile inputFile() { + return inputFile; + } + + @Override + public NewCoverage ofType(CoverageType type) { + Preconditions.checkNotNull(type, "type can't be null"); + this.type = type; + return this; + } + + public CoverageType type() { + return type; + } + + @Override + public NewCoverage lineHits(int line, int hits) { + if (!hitsByLine.containsKey(line)) { + hitsByLine.put(line, hits); + if (hits > 0) { + totalCoveredLines += 1; + } + } + return this; + } + + @Override + public NewCoverage conditions(int line, int conditions, int coveredConditions) { + if (conditions > 0 && !conditionsByLine.containsKey(line)) { + totalConditions += conditions; + totalCoveredConditions += coveredConditions; + conditionsByLine.put(line, conditions); + coveredConditionsByLine.put(line, coveredConditions); + } + return this; + } + + public int coveredLines() { + return totalCoveredLines; + } + + public int linesToCover() { + return hitsByLine.size(); + } + + public int conditions() { + return totalConditions; + } + + public int coveredConditions() { + return totalCoveredConditions; + } + + public SortedMap<Integer, Integer> hitsByLine() { + return Collections.unmodifiableSortedMap(hitsByLine); + } + + public SortedMap<Integer, Integer> conditionsByLine() { + return Collections.unmodifiableSortedMap(conditionsByLine); + } + + public SortedMap<Integer, Integer> coveredConditionsByLine() { + return Collections.unmodifiableSortedMap(coveredConditionsByLine); + } + + @Override + public void doSave() { + Preconditions.checkNotNull(inputFile, "Call onFile() first"); + Preconditions.checkNotNull(type, "Call ofType() first"); + storage.store(this); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/internal/package-info.java new file mode 100644 index 00000000000..4965b41b908 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/internal/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.api.batch.sensor.coverage.internal; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/package-info.java new file mode 100644 index 00000000000..bbf90b94181 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/coverage/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.api.batch.sensor.coverage; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java index 278d9ad1741..70f80865045 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java @@ -32,6 +32,9 @@ import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.coverage.CoverageType; +import org.sonar.api.batch.sensor.coverage.NewCoverage; +import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; import org.sonar.api.batch.sensor.dependency.Dependency; import org.sonar.api.batch.sensor.dependency.NewDependency; import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency; @@ -170,11 +173,52 @@ public class SensorContextTester implements SensorContext { } } + @CheckForNull + public Integer lineHits(String fileKey, CoverageType type, int line) { + Map<CoverageType, DefaultCoverage> defaultCoverageByType = sensorStorage.coverageByComponent.get(fileKey); + if (defaultCoverageByType == null) { + return null; + } + if (defaultCoverageByType.containsKey(type)) { + return defaultCoverageByType.get(type).hitsByLine().get(line); + } + return null; + } + + @CheckForNull + public Integer conditions(String fileKey, CoverageType type, int line) { + Map<CoverageType, DefaultCoverage> defaultCoverageByType = sensorStorage.coverageByComponent.get(fileKey); + if (defaultCoverageByType == null) { + return null; + } + if (defaultCoverageByType.containsKey(type)) { + return defaultCoverageByType.get(type).conditionsByLine().get(line); + } + return null; + } + + @CheckForNull + public Integer coveredConditions(String fileKey, CoverageType type, int line) { + Map<CoverageType, DefaultCoverage> defaultCoverageByType = sensorStorage.coverageByComponent.get(fileKey); + if (defaultCoverageByType == null) { + return null; + } + if (defaultCoverageByType.containsKey(type)) { + return defaultCoverageByType.get(type).coveredConditionsByLine().get(line); + } + return null; + } + @Override public NewHighlighting newHighlighting() { return new DefaultHighlighting(sensorStorage); } + @Override + public NewCoverage newCoverage() { + return new DefaultCoverage(sensorStorage); + } + public List<TypeOfText> highlightingTypeAt(String componentKey, int line, int lineOffset) { DefaultHighlighting syntaxHighlightingData = sensorStorage.highlightingByComponent.get(componentKey); if (syntaxHighlightingData == null) { @@ -240,6 +284,7 @@ public class SensorContextTester implements SensorContext { private Map<String, List<Issue>> issuesByComponent = new HashMap<>(); private Map<String, DefaultHighlighting> highlightingByComponent = new HashMap<>(); + private Map<String, Map<CoverageType, DefaultCoverage>> coverageByComponent = new HashMap<>(); private List<Duplication> duplications = new ArrayList<>(); private List<Dependency> dependencies = new ArrayList<>(); @@ -285,6 +330,15 @@ public class SensorContextTester implements SensorContext { highlightingByComponent.put(getKey(highlighting.inputFile()), highlighting); } + @Override + public void store(DefaultCoverage defaultCoverage) { + String key = getKey(defaultCoverage.inputFile()); + if (!coverageByComponent.containsKey(key)) { + coverageByComponent.put(key, new HashMap<CoverageType, DefaultCoverage>()); + } + coverageByComponent.get(key).put(defaultCoverage.type(), defaultCoverage); + } + @CheckForNull private String getKey(@Nullable InputPath inputPath) { if (inputPath == null) { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java index 121ba2a874c..6f81ce61226 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java @@ -20,6 +20,7 @@ package org.sonar.api.batch.sensor.internal; import org.sonar.api.BatchComponent; +import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; import org.sonar.api.batch.sensor.dependency.Dependency; import org.sonar.api.batch.sensor.duplication.Duplication; import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting; @@ -42,4 +43,9 @@ public interface SensorStorage extends BatchComponent { void store(DefaultHighlighting highlighting); + /** + * @since 5.2 + */ + void store(DefaultCoverage defaultCoverage); + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java index d4ddac91853..7f9a1b1baf9 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java @@ -20,18 +20,16 @@ package org.sonar.api.measures; import com.google.common.collect.Maps; +import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.utils.KeyValueFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.SortedMap; +import java.util.*; /** * @since 2.7 + * @deprecated since 5.2 use {@link SensorContext#newCoverage()} */ +@Deprecated public final class CoverageMeasuresBuilder { /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java index a656a76bbb1..50a5e0c21ff 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java @@ -32,6 +32,10 @@ public interface MutableTestCase extends TestCase { MutableTestCase setStackTrace(@Nullable String s); + /** + * @deprecated since 5.2 not used + */ + @Deprecated MutableTestCase setType(@Nullable String s); MutableTestCase setCoverageBlock(Testable testable, List<Integer> lines); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java index abe7025a02a..a01fa7ae2de 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java @@ -30,7 +30,15 @@ public interface TestCase { } } + /** + * @deprecated since 5.2 not used + */ + @Deprecated String TYPE_UNIT = "UNIT"; + /** + * @deprecated since 5.2 not used + */ + @Deprecated String TYPE_INTEGRATION = "INTEGRATION"; /** |