Skip to content

Commit

Permalink
SONAR-8701 Lines measures are computed using lines from CE Component
Browse files Browse the repository at this point in the history
  • Loading branch information
julienlancelot authored and dbmeneses committed Jan 27, 2017
1 parent 27c1900 commit 6840dc5
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 162 deletions.
Expand Up @@ -30,6 +30,7 @@
import org.sonar.db.component.SnapshotDto;
import org.sonar.scanner.protocol.output.ScannerReport;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.toArray;
import static java.lang.String.format;
import static org.apache.commons.lang.StringUtils.trimToNull;
Expand Down Expand Up @@ -189,6 +190,7 @@ static FileAttributes createFileAttributes(ScannerReport.Component component) {
return null;
}

checkArgument(component.getLines() > 0, "File '%s' has no line", component.getPath());
return new FileAttributes(
component.getIsTest(),
trimToNull(component.getLanguage()),
Expand Down
Expand Up @@ -38,7 +38,7 @@ public class FileAttributes {
public FileAttributes(boolean unitTest, @Nullable String languageKey, int lines) {
this.unitTest = unitTest;
this.languageKey = languageKey;
checkArgument(lines > 0, "Lines has not been set for this file");
checkArgument(lines > 0, "Number of lines must be greater than zero");
this.lines = lines;
}

Expand All @@ -51,6 +51,9 @@ public String getLanguageKey() {
return languageKey;
}

/**
* Number of lines of the file, can never be less than 1
*/
public int getLines() {
return lines;
}
Expand Down
Expand Up @@ -22,7 +22,6 @@
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
import org.sonar.server.computation.task.projectanalysis.component.PathAwareCrawler;
Expand All @@ -38,6 +37,8 @@

import static org.sonar.api.measures.CoreMetrics.ACCESSORS_KEY;
import static org.sonar.api.measures.CoreMetrics.CLASSES_KEY;
import static org.sonar.api.measures.CoreMetrics.DIRECTORIES_KEY;
import static org.sonar.api.measures.CoreMetrics.FILES_KEY;
import static org.sonar.api.measures.CoreMetrics.FUNCTIONS_KEY;
import static org.sonar.api.measures.CoreMetrics.GENERATED_LINES_KEY;
import static org.sonar.api.measures.CoreMetrics.GENERATED_NCLOC_KEY;
Expand All @@ -54,7 +55,6 @@
public class SizeMeasuresStep implements ComputationStep {
private static final CounterStackElementFactory COUNTER_STACK_ELEMENT_FACTORY = new CounterStackElementFactory();
private static final List<Formula> AGGREGATED_SIZE_MEASURE_FORMULAS = ImmutableList.<Formula>of(
createIntSumFormula(LINES_KEY),
createIntSumFormula(GENERATED_LINES_KEY),
createIntSumFormula(NCLOC_KEY),
createIntSumFormula(GENERATED_NCLOC_KEY),
Expand All @@ -75,11 +75,11 @@ public SizeMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRe

@Override
public void execute() {
Metric fileMetric = metricRepository.getByKey(CoreMetrics.FILES_KEY);
Metric directoryMetric = metricRepository.getByKey(CoreMetrics.DIRECTORIES_KEY);

new PathAwareCrawler<>(new FileAndDirectoryMeasureVisitor(directoryMetric, fileMetric))
.visit(treeRootHolder.getRoot());
new PathAwareCrawler<>(new FileAndDirectoryMeasureVisitor(
metricRepository.getByKey(DIRECTORIES_KEY),
metricRepository.getByKey(FILES_KEY),
metricRepository.getByKey(LINES_KEY)))
.visit(treeRootHolder.getRoot());
new PathAwareCrawler<>(FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
.buildFor(AGGREGATED_SIZE_MEASURE_FORMULAS))
.visit(treeRootHolder.getRoot());
Expand All @@ -93,40 +93,44 @@ public String getDescription() {
private class FileAndDirectoryMeasureVisitor extends PathAwareVisitorAdapter<Counter> {
private final Metric directoryMetric;
private final Metric fileMetric;
private final Metric linesMetric;

public FileAndDirectoryMeasureVisitor(Metric directoryMetric, Metric fileMetric) {
public FileAndDirectoryMeasureVisitor(Metric directoryMetric, Metric fileMetric, Metric linesMetric) {
super(CrawlerDepthLimit.LEAVES, POST_ORDER, COUNTER_STACK_ELEMENT_FACTORY);
this.directoryMetric = directoryMetric;
this.fileMetric = fileMetric;
this.linesMetric = linesMetric;
}

@Override
public void visitProject(Component project, Path<Counter> path) {
createMeasures(project, path.current().directories, path.current().files);
createMeasures(project, path.current());
}

@Override
public void visitModule(Component module, Path<Counter> path) {
createMeasures(module, path.current().directories, path.current().files);

path.parent().directories += path.current().directories;
path.parent().files += path.current().files;
createMeasures(module, path.current());
path.parent().aggregate(path.current());
}

@Override
public void visitDirectory(Component directory, Path<Counter> path) {
int fileCount = path.current().files;
if (fileCount > 0) {
createMeasures(directory, 1, fileCount);
measureRepository.add(directory, directoryMetric, newMeasureBuilder().create(1));
measureRepository.add(directory, fileMetric, newMeasureBuilder().create(fileCount));
measureRepository.add(directory, linesMetric, newMeasureBuilder().create(path.current().lines));
path.parent().directories += 1;
path.parent().files += fileCount;
path.parent().lines += path.current().lines;
}
}

private void createMeasures(Component directory, int dirCount, int fileCount) {
if (fileCount > 0) {
measureRepository.add(directory, directoryMetric, newMeasureBuilder().create(dirCount));
measureRepository.add(directory, fileMetric, newMeasureBuilder().create(fileCount));
private void createMeasures(Component directory, Counter counter) {
if (counter.files > 0) {
measureRepository.add(directory, directoryMetric, newMeasureBuilder().create(counter.directories));
measureRepository.add(directory, fileMetric, newMeasureBuilder().create(counter.files));
measureRepository.add(directory, linesMetric, newMeasureBuilder().create(counter.lines));
}
}

Expand All @@ -135,41 +139,47 @@ public void visitFile(Component file, Path<Counter> path) {
if (file.getFileAttributes().isUnitTest()) {
return;
}
int lines = file.getFileAttributes().getLines();
measureRepository.add(file, fileMetric, newMeasureBuilder().create(1));

measureRepository.add(file, linesMetric, newMeasureBuilder().create(lines));
path.parent().lines += lines;
path.parent().files += 1;
}

@Override
public void visitView(Component view, Path<Counter> path) {
createMeasures(view, path.current().directories, path.current().files);
createMeasures(view, path.current());
}

@Override
public void visitSubView(Component subView, Path<Counter> path) {
createMeasures(subView, path.current().directories, path.current().files);

path.parent().directories += path.current().directories;
path.parent().files += path.current().files;
createMeasures(subView, path.current());
path.parent().aggregate(path.current());
}

@Override
public void visitProjectView(Component projectView, Path<Counter> path) {
path.parent().directories += getIntValue(projectView, this.directoryMetric);
path.parent().files += getIntValue(projectView, this.fileMetric);
path.parent().lines += getIntValue(projectView, this.linesMetric);
}

private int getIntValue(Component component, Metric metric) {
Optional<Measure> fileMeasure = measureRepository.getRawMeasure(component, metric);
return fileMeasure.isPresent() ? fileMeasure.get().getIntValue() : 0;
}

}

private static class Counter {
private int lines = 0;
private int files = 0;
private int directories = 0;

void aggregate(Counter counter) {
directories += counter.directories;
files += counter.files;
lines += counter.lines;
}
}

private static class CounterStackElementFactory extends PathAwareVisitorAdapter.SimpleStackElementFactory<Counter> {
Expand All @@ -188,4 +198,5 @@ public Counter createForProjectView(Component projectView) {
return null;
}
}

}
Expand Up @@ -489,18 +489,25 @@ public void createFileAttributes_sets_lines_in_Scanner_Component() {
assertThat(createFileAttributes(newBuilder().setType(FILE).setLines(10).build()).getLines()).isEqualTo(10);
}

@Test
public void fail_with_IAE_when_createFileAttributes_lines_is_not_set() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("File 'src/main/java/Main.java' has no line");
createFileAttributes(newBuilder().setType(FILE).setPath("src/main/java/Main.java").build());
}

@Test
public void fail_with_IAE_when_createFileAttributes_sets_lines_to_0() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Lines has not been set for this file");
createFileAttributes(newBuilder().setType(FILE).setLines(0).build());
expectedException.expectMessage("File 'src/main/java/Main.java' has no line");
createFileAttributes(newBuilder().setType(FILE).setPath("src/main/java/Main.java").setLines(0).build());
}

@Test
public void fail_with_IAE_when_createFileAttributes_lines_is_not_set() throws Exception {
public void fail_with_IAE_when_createFileAttributes_sets_lines_to_less_than_0() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Lines has not been set for this file");
createFileAttributes(newBuilder().setType(FILE).build());
expectedException.expectMessage("File 'src/main/java/Main.java' has no line");
createFileAttributes(newBuilder().setType(FILE).setPath("src/main/java/Main.java").setLines(-10).build());
}

private static class ScannerComponentProvider extends ExternalResource implements Function<Integer, ScannerReport.Component> {
Expand Down
@@ -0,0 +1,80 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program 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.
*
* This program 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.task.projectanalysis.component;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.assertj.core.api.Assertions.assertThat;

public class FileAttributesTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void create_production_file() throws Exception {
FileAttributes underTest = new FileAttributes(true, "java", 10);

assertThat(underTest.isUnitTest()).isTrue();
assertThat(underTest.getLanguageKey()).isEqualTo("java");
assertThat(underTest.getLines()).isEqualTo(10);
}

@Test
public void create_unit_test() throws Exception {
FileAttributes underTest = new FileAttributes(true, "java", 10);

assertThat(underTest.isUnitTest()).isTrue();
assertThat(underTest.getLanguageKey()).isEqualTo("java");
assertThat(underTest.getLines()).isEqualTo(10);
}

@Test
public void create_without_language() throws Exception {
FileAttributes underTest = new FileAttributes(true, null, 10);

assertThat(underTest.isUnitTest()).isTrue();
assertThat(underTest.getLanguageKey()).isNull();
assertThat(underTest.getLines()).isEqualTo(10);
}

@Test
public void fail_with_IAE_when_lines_is_0() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Number of lines must be greater than zero");
new FileAttributes(true, "java", 0);
}

@Test
public void fail_with_IAE_when_lines_is_less_than_0() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Number of lines must be greater than zero");
new FileAttributes(true, "java", -10);
}

@Test
public void test_toString() throws Exception {
assertThat(new FileAttributes(true, "java", 10).toString()).isEqualTo("FileAttributes{languageKey='java', unitTest=true, lines=10}");
assertThat(new FileAttributes(false, null, 1).toString()).isEqualTo("FileAttributes{languageKey='null', unitTest=false, lines=1}");
}
}

0 comments on commit 6840dc5

Please sign in to comment.