summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2015-07-03 12:42:14 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2015-07-03 13:14:43 +0200
commit077bedd2ae941d320372c7c44a170be23a1679a5 (patch)
treedf174bc142d2102b00442f6e39b2a4007d91718c /server
parent8d9953d57840d24a7d99d6f263837eaf9ef6addf (diff)
downloadsonarqube-077bedd2ae941d320372c7c44a170be23a1679a5.tar.gz
sonarqube-077bedd2ae941d320372c7c44a170be23a1679a5.zip
SONAR-6680 Move computation of measure Quality Profile to Compute Engine
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/formula/CoreFormulaRepositoryImpl.java114
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStep.java28
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/formula/CoreFormulaRepositoryImplTest.java (renamed from server/sonar-server/src/main/java/org/sonar/server/computation/formula/FormulaRepositoryImpl.java)17
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStepTest.java58
5 files changed, 195 insertions, 30 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java
index ec4863798e0..00b8cab25a9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java
@@ -43,14 +43,14 @@ import org.sonar.server.computation.component.ProjectSettingsRepository;
import org.sonar.server.computation.component.TreeRootHolderImpl;
import org.sonar.server.computation.debt.DebtModelHolderImpl;
import org.sonar.server.computation.event.EventRepositoryImpl;
-import org.sonar.server.computation.formula.FormulaRepositoryImpl;
+import org.sonar.server.computation.formula.CoreFormulaRepositoryImpl;
import org.sonar.server.computation.issue.BaseIssuesLoader;
-import org.sonar.server.computation.issue.DebtCalculator;
-import org.sonar.server.computation.issue.IssueCounter;
import org.sonar.server.computation.issue.DebtAggregator;
+import org.sonar.server.computation.issue.DebtCalculator;
import org.sonar.server.computation.issue.DefaultAssignee;
import org.sonar.server.computation.issue.IssueAssigner;
import org.sonar.server.computation.issue.IssueCache;
+import org.sonar.server.computation.issue.IssueCounter;
import org.sonar.server.computation.issue.IssueLifecycle;
import org.sonar.server.computation.issue.IssueVisitors;
import org.sonar.server.computation.issue.NewDebtAggregator;
@@ -160,7 +160,7 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co
EventRepositoryImpl.class,
ProjectSettingsRepository.class,
DbIdsRepository.class,
- FormulaRepositoryImpl.class,
+ CoreFormulaRepositoryImpl.class,
QualityGateServiceImpl.class,
EvaluationResultTextConverterImpl.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/formula/CoreFormulaRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/formula/CoreFormulaRepositoryImpl.java
new file mode 100644
index 00000000000..9b729e2bd64
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/formula/CoreFormulaRepositoryImpl.java
@@ -0,0 +1,114 @@
+/*
+ * 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.server.computation.formula;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+import static org.sonar.api.measures.CoreMetrics.CLASSES_KEY;
+import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_KEY;
+import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES_KEY;
+import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILES_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_KEY;
+import static org.sonar.api.measures.CoreMetrics.FUNCTIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY;
+import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_KEY;
+import static org.sonar.api.measures.CoreMetrics.GENERATED_LINES_KEY;
+import static org.sonar.api.measures.CoreMetrics.GENERATED_NCLOC_KEY;
+import static org.sonar.api.measures.CoreMetrics.STATEMENTS_KEY;
+
+public class CoreFormulaRepositoryImpl implements FormulaRepository {
+
+ private static final List<Formula> FORMULAS = ImmutableList.<Formula>of(
+ // TODO When all decorators will be moved to CE, uncomment commented lines to activate all formulas and remove formulas declaration in
+ // {@link org.sonar.api.measures.CoreMetrics}
+ // Sum formulas
+ // new SumFormula(LINES_KEY),
+ new SumFormula(GENERATED_LINES_KEY),
+ // new SumFormula(NCLOC_KEY),
+ new SumFormula(GENERATED_NCLOC_KEY),
+ new SumFormula(CLASSES_KEY),
+ new SumFormula(FUNCTIONS_KEY),
+ new SumFormula(STATEMENTS_KEY),
+ // new SumFormula(PUBLIC_API_KEY),
+ // new SumFormula(COMMENT_LINES_KEY),
+ // new SumFormula(PUBLIC_UNDOCUMENTED_API_KEY),
+ new SumFormula(COMPLEXITY_KEY),
+ new SumFormula(COMPLEXITY_IN_CLASSES_KEY),
+ new SumFormula(COMPLEXITY_IN_FUNCTIONS_KEY),
+ // new SumFormula(LINES_TO_COVER_KEY),
+ // new SumFormula(NEW_LINES_TO_COVER_KEY),
+ // new SumFormula(UNCOVERED_LINES_KEY),
+ // new SumFormula(NEW_UNCOVERED_LINES_KEY),
+ // new SumFormula(CONDITIONS_TO_COVER_KEY),
+ // new SumFormula(NEW_CONDITIONS_TO_COVER_KEY),
+ // new SumFormula(UNCOVERED_CONDITIONS_KEY),
+ // new SumFormula(NEW_UNCOVERED_CONDITIONS_KEY),
+ // new SumFormula(IT_LINES_TO_COVER_KEY),
+ // new SumFormula(NEW_IT_LINES_TO_COVER_KEY),
+ // new SumFormula(IT_UNCOVERED_LINES_KEY),
+ // new SumFormula(NEW_IT_UNCOVERED_LINES_KEY),
+ // new SumFormula(IT_CONDITIONS_TO_COVER_KEY),
+ // new SumFormula(NEW_IT_CONDITIONS_TO_COVER_KEY),
+ // new SumFormula(IT_UNCOVERED_CONDITIONS_KEY),
+ // new SumFormula(NEW_IT_UNCOVERED_CONDITIONS_KEY),
+ // new SumFormula(OVERALL_LINES_TO_COVER_KEY),
+ // new SumFormula(NEW_OVERALL_LINES_TO_COVER_KEY),
+ // new SumFormula(OVERALL_UNCOVERED_LINES_KEY),
+ // new SumFormula(NEW_OVERALL_UNCOVERED_LINES_KEY),
+ // new SumFormula(OVERALL_CONDITIONS_TO_COVER_KEY),
+ // new SumFormula(NEW_OVERALL_CONDITIONS_TO_COVER_KEY),
+ // new SumFormula(OVERALL_UNCOVERED_CONDITIONS_KEY),
+ // new SumFormula(NEW_OVERALL_UNCOVERED_CONDITIONS_KEY),
+
+ // Distribution formulas
+ new DistributionFormula(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY),
+ new DistributionFormula(FILE_COMPLEXITY_DISTRIBUTION_KEY),
+
+ // Average formulas, must be executed after all sum formulas as they depend on their measures
+ AverageFormula.Builder.newBuilder().setOutputMetricKey(FILE_COMPLEXITY_KEY)
+ .setMainMetricKey(COMPLEXITY_KEY)
+ .setByMetricKey(FILES_KEY)
+ .build(),
+ AverageFormula.Builder.newBuilder().setOutputMetricKey(CLASS_COMPLEXITY_KEY)
+ .setMainMetricKey(COMPLEXITY_IN_CLASSES_KEY)
+ .setByMetricKey(CLASSES_KEY)
+ .setFallbackMetricKey(COMPLEXITY_KEY)
+ .build(),
+ AverageFormula.Builder.newBuilder().setOutputMetricKey(FUNCTION_COMPLEXITY_KEY)
+ .setMainMetricKey(COMPLEXITY_IN_FUNCTIONS_KEY)
+ .setByMetricKey(FUNCTIONS_KEY)
+ .setFallbackMetricKey(COMPLEXITY_KEY)
+ .build()
+ );
+
+ /**
+ * Return list of formulas that was previously provided by CoreMetrics
+ */
+ @Override
+ public List<Formula> getFormulas() {
+ return FORMULAS;
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStep.java
index 37f64e6c62f..e1d81e03866 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStep.java
@@ -23,6 +23,7 @@ package org.sonar.server.computation.step;
import com.google.common.base.Optional;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.CheckForNull;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.ComponentVisitor;
import org.sonar.server.computation.component.PathAwareVisitor;
@@ -96,8 +97,11 @@ public class ComputeFormulaMeasuresStep implements ComputationStep {
private void processNotFile(Component component, PathAwareVisitor.Path<Counters> path) {
for (Formula formula : formulaRepository.getFormulas()) {
Counter counter = path.current().getCounter(formula.getOutputMetricKey());
- addNewMeasure(component, path, formula, counter);
- aggregateToParent(path, formula, counter);
+ // If there were no file under this node, the counter won't be initialized
+ if (counter != null) {
+ addNewMeasure(component, formula, counter);
+ aggregateToParent(path, formula, counter);
+ }
}
}
@@ -106,12 +110,12 @@ public class ComputeFormulaMeasuresStep implements ComputationStep {
for (Formula formula : formulaRepository.getFormulas()) {
Counter counter = newCounter(formula);
counter.aggregate(counterContext);
- addNewMeasure(file, path, formula, counter);
+ addNewMeasure(file, formula, counter);
aggregateToParent(path, formula, counter);
}
}
- private void addNewMeasure(Component component, PathAwareVisitor.Path<Counters> path, Formula formula, Counter counter) {
+ private void addNewMeasure(Component component, Formula formula, Counter counter) {
Metric metric = metricRepository.getByKey(formula.getOutputMetricKey());
Optional<Measure> measure = formula.createMeasure(counter, component.getType());
if (measure.isPresent()) {
@@ -136,23 +140,23 @@ public class ComputeFormulaMeasuresStep implements ComputationStep {
}
private static class Counters {
- Map<String, Counter> countersByFormula = new HashMap<>();
+ Map<String, Counter> countersByMetricKey = new HashMap<>();
public void aggregate(String metricKey, Counter childCounter) {
- Counter counter = countersByFormula.get(metricKey);
+ Counter counter = countersByMetricKey.get(metricKey);
if (counter == null) {
- countersByFormula.put(metricKey, childCounter);
+ countersByMetricKey.put(metricKey, childCounter);
} else {
counter.aggregate(childCounter);
}
}
+ /**
+ * Counter can be null on a level when it has not been fed by children levels
+ */
+ @CheckForNull
public Counter getCounter(String metricKey) {
- Counter counter = countersByFormula.get(metricKey);
- if (counter == null) {
- throw new IllegalStateException(String.format("No counter found on metric '%s'", metricKey));
- }
- return counter;
+ return countersByMetricKey.get(metricKey);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/formula/FormulaRepositoryImpl.java b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/CoreFormulaRepositoryImplTest.java
index 8d3ee9ab01c..ddba6cc3203 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/formula/FormulaRepositoryImpl.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/CoreFormulaRepositoryImplTest.java
@@ -20,16 +20,15 @@
package org.sonar.server.computation.formula;
-import java.util.Collections;
-import java.util.List;
+import org.junit.Test;
-public class FormulaRepositoryImpl implements FormulaRepository {
+import static org.assertj.core.api.Assertions.assertThat;
- /**
- * TODO Move formula from CoreMetrics here
- */
- public List<Formula> getFormulas() {
- return Collections.emptyList();
- }
+public class CoreFormulaRepositoryImplTest {
+
+ @Test
+ public void check_formulas_are_not_empty() throws Exception {
+ assertThat(new CoreFormulaRepositoryImpl().getFormulas()).isNotEmpty();
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStepTest.java
index 02ffc18dfd4..f28f0095349 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeFormulaMeasuresStepTest.java
@@ -22,7 +22,6 @@ package org.sonar.server.computation.step;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
-import org.assertj.guava.api.Assertions;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -39,6 +38,7 @@ import org.sonar.server.computation.measure.MeasureRepositoryRule;
import org.sonar.server.computation.metric.MetricRepositoryRule;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
@@ -127,10 +127,58 @@ public class ComputeFormulaMeasuresStepTest {
sut.execute();
- Assertions.assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
- Assertions.assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
- Assertions.assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
- Assertions.assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
+ }
+
+ @Test
+ public void add_no_measure_when_no_file() throws Exception {
+ DumbComponent project = DumbComponent.builder(PROJECT, 1)
+ .addChildren(
+ DumbComponent.builder(MODULE, 11)
+ .addChildren(
+ DumbComponent.builder(DIRECTORY, 111).build()
+ ).build()
+ ).build();
+
+ treeRootHolder.setRoot(project);
+
+ sut.execute();
+
+ assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
+ }
+
+ @Test
+ public void add_no_measure_on_module_without_file() throws Exception {
+ DumbComponent project = DumbComponent.builder(PROJECT, 1)
+ .addChildren(
+ DumbComponent.builder(MODULE, 11)
+ .addChildren(
+ DumbComponent.builder(DIRECTORY, 111).build()
+ ).build(),
+ DumbComponent.builder(MODULE, 12)
+ .addChildren(
+ DumbComponent.builder(DIRECTORY, 121)
+ .addChildren(
+ builder(Component.Type.FILE, 1211).build()
+ ).build()
+ ).build()
+ ).build();
+ treeRootHolder.setRoot(project);
+ measureRepository.addRawMeasure(1211, CoreMetrics.LINES_KEY, newMeasureBuilder().create(10));
+
+ sut.execute();
+
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
+ assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
+ assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
}
private static class FakeFormula implements Formula<FakeCounter> {