Skip to content

Commit a876952

Browse files
authored
Merge pull request #151 from isaacwang4076/modular-code-coverage
Added support for modular code coverage and capability to specify a reports directory
2 parents 94173f9 + 53b8be2 commit a876952

File tree

7 files changed

+204
-18
lines changed

7 files changed

+204
-18
lines changed

sonar-swift-plugin/src/main/java/org/sonar/plugins/swift/coverage/CoberturaReportParser.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ private void collectPackageMeasures(SMInputCursor pack) throws XMLStreamExceptio
8484
collectFileMeasures(pack.descendantElementCursor("class"), builderByFilename);
8585
for (Map.Entry<String, CoverageMeasuresBuilder> entry : builderByFilename.entrySet()) {
8686
String filePath = entry.getKey();
87+
filePath = getAdjustedPathIfProjectIsModule(filePath);
88+
if (filePath == null) {
89+
continue;
90+
}
8791
File file = new File(fileSystem.baseDir(), filePath);
8892
InputFile inputFile = fileSystem.inputFile(fileSystem.predicates().hasAbsolutePath(file.getAbsolutePath()));
8993

@@ -98,6 +102,7 @@ private void collectPackageMeasures(SMInputCursor pack) throws XMLStreamExceptio
98102
context.saveMeasure(resource, measure);
99103
}
100104
}
105+
LOGGER.info("Successfully collected measures for file {}", file.getPath());
101106
}
102107
}
103108
}
@@ -106,6 +111,18 @@ private boolean resourceExists(Resource file) {
106111
return context.getResource(file) != null;
107112
}
108113

114+
private String getAdjustedPathIfProjectIsModule(String filePath) {
115+
if (project.isModule()) {
116+
// the file doesn't belong to the module we're analyzing
117+
if (!filePath.startsWith(project.path())) {
118+
return null;
119+
}
120+
// fileSystem.baseDir() will include the module path, so we need to get rid of it here
121+
return filePath.substring(project.path().length());
122+
}
123+
return filePath;
124+
}
125+
109126
private static void collectFileMeasures(SMInputCursor clazz,
110127
Map<String, CoverageMeasuresBuilder> builderByFilename) throws XMLStreamException {
111128
while (clazz.getNext() != null) {

sonar-swift-plugin/src/main/java/org/sonar/plugins/swift/coverage/ReportFilesFinder.java

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,57 +18,106 @@
1818
package org.sonar.plugins.swift.coverage;
1919

2020
import org.apache.tools.ant.DirectoryScanner;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
2123
import org.sonar.api.config.Settings;
2224

2325
import java.io.File;
26+
import java.util.Arrays;
2427
import java.util.ArrayList;
2528
import java.util.List;
2629

2730
final class ReportFilesFinder {
2831

32+
private static final Logger LOGGER = LoggerFactory.getLogger(ReportFilesFinder.class);
33+
2934
private final Settings conf;
30-
private final String settingsKey;
31-
private final String settingsDefault;
35+
private final String settingsReportKey;
36+
private final String settingsReportDefault;
37+
private final String settingsDirectoryKey;
3238

33-
public ReportFilesFinder(final Settings settings, final String key, final String defaultValue) {
39+
public ReportFilesFinder(final Settings settings, final String settingsReportKey, final String settingsReportDefault, final String settingsDirectoryKey) {
3440

3541
conf = settings;
36-
settingsKey = key;
37-
settingsDefault = defaultValue;
42+
this.settingsReportKey = settingsReportKey;
43+
this.settingsReportDefault = settingsReportDefault;
44+
this.settingsDirectoryKey = settingsDirectoryKey;
45+
}
46+
47+
public List<File> reportsIn(final String baseDirectory) {
48+
49+
final String reportDirectory = getReportDirectory(baseDirectory, baseDirectory); // the root directory in this case is the base directory
50+
final String reportPattern = getReportPattern();
51+
return reportsInHelper(reportDirectory, reportPattern);
52+
}
53+
54+
public List<File> reportsIn(final String module, final String rootDirectory, final String baseDirectory) {
55+
56+
final String reportDirectory = getReportDirectory(module, rootDirectory, baseDirectory);
57+
final String reportPattern = getReportPattern(module);
58+
return reportsInHelper(reportDirectory, reportPattern);
3859
}
3960

40-
public List<File> reportsIn(final String baseDirPath) {
61+
private List<File> reportsInHelper(final String reportDirectory, final String reportPattern) {
4162

42-
final String[] relPaths = filesMathingPattern(baseDirPath, reportPattern());
63+
final String[] relPaths = filesMathingPattern(reportDirectory, reportPattern);
4364

4465
final List<File> reports = new ArrayList<File>();
4566

4667
for (final String relPath : relPaths) {
47-
reports.add(new File(baseDirPath, relPath));
68+
reports.add(new File(reportDirectory, relPath));
4869
}
4970

5071
return reports;
5172
}
5273

53-
private String[] filesMathingPattern(final String baseDirPath, final String reportPath) {
74+
private String[] filesMathingPattern(final String reportDirectory, final String reportPath) {
5475

5576
final DirectoryScanner scanner = new DirectoryScanner();
5677
scanner.setIncludes(new String[] { reportPath });
57-
scanner.setBasedir(new File(baseDirPath));
78+
scanner.setBasedir(new File(reportDirectory));
5879
scanner.scan();
5980

81+
LOGGER.info("Files found in directory '{}' including '{}': {}", reportDirectory, reportPath, Arrays.toString(scanner.getIncludedFiles()));
82+
6083
return scanner.getIncludedFiles();
6184
}
6285

63-
private String reportPattern() {
64-
65-
String reportPath = conf.getString(settingsKey);
86+
private String getReportPattern() {
6687

88+
String reportPath = conf.getString(settingsReportKey);
6789
if (reportPath == null) {
68-
reportPath = settingsDefault;
90+
reportPath = settingsReportDefault;
6991
}
92+
return reportPath;
93+
}
94+
95+
private String getReportPattern(final String module) {
7096

97+
String reportPath = conf.getString(module + "." + settingsReportKey);
98+
if (reportPath == null) {
99+
return getReportPattern();
100+
}
71101
return reportPath;
72102
}
73103

104+
private String getReportDirectory(final String rootDirectory, final String baseDirectory) {
105+
106+
String reportDirectory = conf.getString(settingsDirectoryKey);
107+
if (reportDirectory == null) {
108+
return baseDirectory;
109+
}
110+
return rootDirectory + "/" + reportDirectory;
111+
}
112+
113+
114+
private String getReportDirectory(final String module, final String rootDirectory, final String baseDirectory) {
115+
116+
String reportDirectory = conf.getString(module + "." + settingsDirectoryKey);
117+
if (reportDirectory == null) {
118+
return getReportDirectory(rootDirectory, baseDirectory);
119+
}
120+
return rootDirectory + "/" + reportDirectory;
121+
}
122+
74123
}

sonar-swift-plugin/src/main/java/org/sonar/plugins/swift/coverage/SwiftCoberturaSensor.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.sonar.plugins.swift.lang.core.Swift;
3030

3131
import java.io.File;
32+
import java.util.List;
3233

3334

3435
public final class SwiftCoberturaSensor implements Sensor {
@@ -37,6 +38,7 @@ public final class SwiftCoberturaSensor implements Sensor {
3738

3839
public static final String REPORT_PATTERN_KEY = SwiftPlugin.PROPERTY_PREFIX + ".coverage.reportPattern";
3940
public static final String DEFAULT_REPORT_PATTERN = "sonar-reports/coverage-swift*.xml";
41+
public static final String REPORT_DIRECTORY_KEY = SwiftPlugin.PROPERTY_PREFIX + ".coverage.reportDirectory";
4042

4143
private final ReportFilesFinder reportFilesFinder;
4244

@@ -51,24 +53,44 @@ public SwiftCoberturaSensor(final FileSystem fileSystem, final PathResolver path
5153
this.fileSystem = fileSystem;
5254
this.pathResolver = pathResolver;
5355

54-
reportFilesFinder = new ReportFilesFinder(settings, REPORT_PATTERN_KEY, DEFAULT_REPORT_PATTERN);
56+
reportFilesFinder = new ReportFilesFinder(settings, REPORT_PATTERN_KEY, DEFAULT_REPORT_PATTERN, REPORT_DIRECTORY_KEY);
5557
}
5658

5759
public boolean shouldExecuteOnProject(final Project project) {
5860

5961
this.project = project;
6062

61-
return project.isRoot() && fileSystem.languages().contains(Swift.KEY);
63+
return fileSystem.languages().contains(Swift.KEY);
6264
}
6365

6466
public void analyse(final Project project, final SensorContext context) {
6567

66-
6768
final String projectBaseDir = fileSystem.baseDir().getPath();
69+
LOGGER.info("Analyzing directory: {}", projectBaseDir);
70+
71+
List<File> reports;
72+
if (project.isRoot()) {
73+
reports = reportFilesFinder.reportsIn(projectBaseDir);
74+
}
75+
else {
76+
final String module = project.getName();
77+
final String rootDir = getRootDirectory(project);
78+
reports = reportFilesFinder.reportsIn(module, rootDir, projectBaseDir);
79+
}
6880

69-
for (final File report : reportFilesFinder.reportsIn(projectBaseDir)) {
81+
for (final File report : reports) {
7082
LOGGER.info("Processing coverage report {}", report);
7183
CoberturaReportParser.parseReport(report, fileSystem, project, context);
7284
}
7385
}
86+
87+
private String getRootDirectory(Project project) {
88+
final String projectBaseDir = fileSystem.baseDir().getPath();
89+
if (project.isRoot()) {
90+
return projectBaseDir;
91+
} else {
92+
final String modulePath = project.path();
93+
return projectBaseDir.substring(0, projectBaseDir.length() - modulePath.length());
94+
}
95+
}
7496
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/**
2+
* backelite-sonar-swift-plugin - Enables analysis of Swift projects into SonarQube.
3+
* Copyright © 2015 Backelite (${email})
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package org.sonar.plugins.swift.coverage;
19+
20+
import java.io.*;
21+
import java.util.*;
22+
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
26+
import org.sonar.api.config.Settings;
27+
import org.sonar.plugins.swift.lang.core.Swift;
28+
29+
import static org.junit.Assert.*;
30+
import static org.mockito.Mockito.*;
31+
32+
public class ReportFilesFinderTest {
33+
34+
private static final String TEST_REPORT_PATTERN = "**/cobertura.xml";
35+
private static final String TEST_MATERIALS_DIR = "./src/test/resources/coverage";
36+
private static final String TEST_MOD_NAME = "myMod";
37+
private static final File REPORT_PATH_1 = new File(TEST_MATERIALS_DIR + "/dir1/cobertura.xml");
38+
private static final File REPORT_PATH_2 = new File(TEST_MATERIALS_DIR + "/dir2/cobertura.xml");
39+
private static final File REPORT_PATH_3 = new File(TEST_MATERIALS_DIR + "/dir3/cobertura.xml");
40+
41+
private Settings settings;
42+
private ReportFilesFinder reportFilesFinder;
43+
44+
@Before
45+
public void setUp() {
46+
settings = mock(Settings.class);
47+
when(settings.getString(SwiftCoberturaSensor.REPORT_PATTERN_KEY)).thenReturn(TEST_REPORT_PATTERN);
48+
when(settings.getString(TEST_MOD_NAME + "." + SwiftCoberturaSensor.REPORT_PATTERN_KEY)).thenReturn(TEST_REPORT_PATTERN);
49+
50+
reportFilesFinder = new ReportFilesFinder(settings, SwiftCoberturaSensor.REPORT_PATTERN_KEY,
51+
SwiftCoberturaSensor.DEFAULT_REPORT_PATTERN, SwiftCoberturaSensor.REPORT_DIRECTORY_KEY);
52+
}
53+
54+
@Test
55+
public void findsFoldersInRootWithNoReportsDirectory() {
56+
assertSameFiles(Arrays.asList(REPORT_PATH_1, REPORT_PATH_2, REPORT_PATH_3), reportFilesFinder.reportsIn(TEST_MATERIALS_DIR));
57+
}
58+
59+
@Test
60+
public void findsFoldersInRootWithReportsDirectory() {
61+
when(settings.getString(SwiftCoberturaSensor.REPORT_DIRECTORY_KEY)).thenReturn("/dir1");
62+
assertSameFiles(Arrays.asList(REPORT_PATH_1), reportFilesFinder.reportsIn(TEST_MATERIALS_DIR));
63+
}
64+
65+
@Test
66+
public void findsFoldersInModuleWithNoReportsDirectory() {
67+
assertSameFiles(Arrays.asList(REPORT_PATH_1), reportFilesFinder.reportsIn(TEST_MOD_NAME, TEST_MATERIALS_DIR, TEST_MATERIALS_DIR + "/dir1"));
68+
}
69+
70+
@Test
71+
public void findsFoldersInModuleWithDefaultReportsDirectory() {
72+
when(settings.getString(SwiftCoberturaSensor.REPORT_DIRECTORY_KEY)).thenReturn("/dir2");
73+
assertSameFiles(Arrays.asList(REPORT_PATH_2), reportFilesFinder.reportsIn(TEST_MOD_NAME, TEST_MATERIALS_DIR, TEST_MATERIALS_DIR + "/dir1"));
74+
}
75+
76+
@Test
77+
public void findsFoldersInModuleWithModuleReportsDirectory() {
78+
when(settings.getString(SwiftCoberturaSensor.REPORT_DIRECTORY_KEY)).thenReturn("/dir2");
79+
when(settings.getString(TEST_MOD_NAME + "." + SwiftCoberturaSensor.REPORT_DIRECTORY_KEY)).thenReturn("/dir3");
80+
assertSameFiles(Arrays.asList(REPORT_PATH_3), reportFilesFinder.reportsIn(TEST_MOD_NAME, TEST_MATERIALS_DIR, TEST_MATERIALS_DIR + "/dir1"));
81+
}
82+
83+
private void assertSameFiles(List<File> list1, List<File> list2) {
84+
assertEquals(getPaths(list1), getPaths(list2));
85+
}
86+
87+
private Set<String> getPaths(List<File> files) {
88+
Set<String> paths = new HashSet();
89+
for (File file: files) {
90+
try {
91+
paths.add(file.getCanonicalPath());
92+
} catch (IOException e) {
93+
fail(e.toString());
94+
}
95+
}
96+
return paths;
97+
}
98+
}

sonar-swift-plugin/src/test/resources/coverage/dir1/cobertura.xml

Whitespace-only changes.

sonar-swift-plugin/src/test/resources/coverage/dir2/cobertura.xml

Whitespace-only changes.

sonar-swift-plugin/src/test/resources/coverage/dir3/cobertura.xml

Whitespace-only changes.

0 commit comments

Comments
 (0)