Skip to content

Commit e3cc5ec

Browse files
SCANMAVEN-216 scanAll includes Java and Kotlin files if sonar.java.binaries and sonar.java.libraries are set (#222)
1 parent b772d4c commit e3cc5ec

File tree

10 files changed

+200
-74
lines changed

10 files changed

+200
-74
lines changed

src/main/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ public class MavenProjectConverter {
8989

9090
public static final String FINDBUGS_EXCLUDE_FILTERS = "sonar.findbugs.excludeFilters";
9191

92-
private static final String JAVA_PROJECT_MAIN_BINARY_DIRS = "sonar.java.binaries";
92+
public static final String JAVA_PROJECT_MAIN_BINARY_DIRS = "sonar.java.binaries";
9393

94-
private static final String JAVA_PROJECT_MAIN_LIBRARIES = "sonar.java.libraries";
94+
public static final String JAVA_PROJECT_MAIN_LIBRARIES = "sonar.java.libraries";
9595

9696
private static final String SONAR_JAVA_JDK_HOME_PROPERTY = "sonar.java.jdkHome";
9797

src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapper.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,15 @@ Map<String, String> collectProperties()
124124
Properties userProperties = session.getUserProperties();
125125
Map<String, String> props = mavenProjectConverter.configure(sortedProjects, topLevelProject, userProperties);
126126
props.putAll(propertyDecryptor.decryptProperties(props));
127-
128127
if (shouldCollectAllSources(userProperties)) {
129128
log.info("Parameter " + MavenScannerProperties.PROJECT_SCAN_ALL_SOURCES + " is enabled. The scanner will attempt to collect additional sources.");
130129
if (mavenProjectConverter.isSourceDirsOverridden()) {
131130
log.warn(notCollectingAdditionalSourcesBecauseOf(ScanProperties.PROJECT_SOURCE_DIRS));
132131
} else if (mavenProjectConverter.isTestDirsOverridden()) {
133132
log.warn(notCollectingAdditionalSourcesBecauseOf(ScanProperties.PROJECT_TEST_DIRS));
134133
} else {
135-
collectAllSources(props);
134+
boolean shouldCollectJavaAndKotlinSources = isUserDefinedJavaBinaries(userProperties);
135+
collectAllSources(props, shouldCollectJavaAndKotlinSources);
136136
}
137137
}
138138

@@ -162,7 +162,7 @@ private static Set<Path> excludedReportFiles(Map<String, String> props) {
162162
}
163163

164164
@VisibleForTesting
165-
void collectAllSources(Map<String, String> props) {
165+
void collectAllSources(Map<String, String> props, boolean shouldCollectJavaAndKotlinSources) {
166166
String projectBasedir = props.get(ScanProperties.PROJECT_BASEDIR);
167167
// Exclude the files and folders covered by sonar.sources and sonar.tests (and sonar.exclusions) as computed by the MavenConverter
168168
// Combine all the sonar.sources at the top-level and by module
@@ -178,9 +178,7 @@ void collectAllSources(Map<String, String> props) {
178178
Set<Path> existingSources = coveredSources.stream()
179179
.map(Paths::get)
180180
.collect(Collectors.toSet());
181-
Set<Path> excludedFiles = excludedReportFiles(props);
182-
183-
SourceCollector visitor = new SourceCollector(existingSources, mavenProjectConverter.getSkippedBasedDirs(), excludedFiles);
181+
SourceCollector visitor = new SourceCollector(existingSources, mavenProjectConverter.getSkippedBasedDirs(), excludedReportFiles(props), shouldCollectJavaAndKotlinSources);
184182
Files.walkFileTree(Paths.get(projectBasedir), visitor);
185183
collectedSources = visitor.getCollectedSources().stream()
186184
.map(file -> file.toAbsolutePath().toString())
@@ -194,6 +192,11 @@ void collectAllSources(Map<String, String> props) {
194192
}
195193
}
196194

195+
private static boolean isUserDefinedJavaBinaries(Properties userProperties) {
196+
return userProperties.containsKey(MavenProjectConverter.JAVA_PROJECT_MAIN_LIBRARIES) &&
197+
userProperties.containsKey(MavenProjectConverter.JAVA_PROJECT_MAIN_BINARY_DIRS);
198+
}
199+
197200
private void checkSQVersion() {
198201
if (isVersionPriorTo("5.6")) {
199202
throw new UnsupportedOperationException(UNSUPPORTED_BELOW_SONARQUBE_56_MESSAGE);

src/main/java/org/sonarsource/scanner/maven/bootstrap/SourceCollector.java

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import java.util.HashSet;
2929
import java.util.Locale;
3030
import java.util.Set;
31+
import java.util.stream.Collectors;
32+
import java.util.stream.Stream;
3133
import java.util.stream.StreamSupport;
3234

3335
public class SourceCollector implements FileVisitor<Path> {
@@ -44,54 +46,59 @@ public class SourceCollector implements FileVisitor<Path> {
4446
)
4547
);
4648

47-
private static final Set<String> EXCLUDED_EXTENSIONS = new HashSet<>(
48-
Arrays.asList(
49-
"jar",
50-
"war",
51-
"class",
52-
"ear",
53-
"nar",
54-
// Archives
55-
"DS_Store",
56-
"zip",
57-
"7z",
58-
"rar",
59-
"gz",
60-
"tar",
61-
"xz",
62-
// log
63-
"log",
64-
// temp files
65-
"bak",
66-
"tmp",
67-
"swp",
68-
// ide files
69-
"iml",
70-
"ipr",
71-
"iws",
72-
"nib",
73-
"log",
74-
"java",
75-
"jav",
76-
"kt",
77-
"scala"
78-
)
79-
);
49+
private static final Set<String> EXCLUDED_EXTENSIONS_WITH_JAVA_AND_KOTLIN = Stream.of(
50+
".jar",
51+
".war",
52+
".class",
53+
".ear",
54+
".nar",
55+
// Archives
56+
".DS_Store",
57+
".zip",
58+
".7z",
59+
".rar",
60+
".gz",
61+
".tar",
62+
".xz",
63+
// log
64+
".log",
65+
// temp files
66+
".bak",
67+
".tmp",
68+
".swp",
69+
// ide files
70+
".iml",
71+
".ipr",
72+
".iws",
73+
".nib",
74+
".log")
75+
.map(ext -> ext.toLowerCase(Locale.ROOT))
76+
.collect(Collectors.toSet());
77+
78+
private static final Set<String> EXCLUDED_EXTENSIONS_WITHOUT_JAVA_AND_KOTLIN = Stream.concat(EXCLUDED_EXTENSIONS_WITH_JAVA_AND_KOTLIN.stream(), Stream.of(
79+
".java",
80+
".jav",
81+
".kt")).map(ext -> ext.toLowerCase(Locale.ROOT))
82+
.collect(Collectors.toSet());
83+
8084
private final Set<Path> existingSources;
8185
private final Set<Path> directoriesToIgnore;
8286
private final Set<Path> excludedFiles;
87+
private final Set<String> excludedExtensions;
8388

8489
public Set<Path> getCollectedSources() {
8590
return collectedSources;
8691
}
8792

8893
private final Set<Path> collectedSources = new HashSet<>();
8994

90-
public SourceCollector(Set<Path> existingSources, Set<Path> directoriesToIgnore, Set<Path> excludedFiles) {
95+
public SourceCollector(Set<Path> existingSources, Set<Path> directoriesToIgnore, Set<Path> excludedFiles, boolean shouldCollectJavaAndKotlinSources) {
9196
this.existingSources = existingSources;
9297
this.directoriesToIgnore = directoriesToIgnore;
9398
this.excludedFiles = excludedFiles;
99+
this.excludedExtensions = shouldCollectJavaAndKotlinSources ? EXCLUDED_EXTENSIONS_WITH_JAVA_AND_KOTLIN : EXCLUDED_EXTENSIONS_WITHOUT_JAVA_AND_KOTLIN;
94100
}
101+
95102
@Override
96103
public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
97104
if (
@@ -120,12 +127,11 @@ private boolean isCoveredByExistingSources(Path path) {
120127

121128
@Override
122129
public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) {
123-
if (
124-
!excludedFiles.contains(path) &&
125-
EXCLUDED_EXTENSIONS.stream().noneMatch(ext -> path.toString().endsWith(ext)) &&
126-
existingSources.stream().noneMatch(path::equals)
127-
) {
128-
collectedSources.add(path);
130+
if (!excludedFiles.contains(path) && existingSources.stream().noneMatch(path::equals)) {
131+
String lowerCaseFileName = path.getFileName().toString().toLowerCase(Locale.ROOT);
132+
if (excludedExtensions.stream().noneMatch(lowerCaseFileName::endsWith)) {
133+
collectedSources.add(path);
134+
}
129135
}
130136
return FileVisitResult.CONTINUE;
131137
}

src/test/java/org/sonarsource/scanner/maven/SonarQubeMojoTest.java

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.io.FileInputStream;
2424
import java.io.FileNotFoundException;
2525
import java.io.IOException;
26+
import java.nio.file.Path;
2627
import java.util.Arrays;
2728
import java.util.Map;
2829
import java.util.Properties;
@@ -104,6 +105,50 @@ public void shouldExportOverridenWarWebSource() throws Exception {
104105
+ new File(baseDir, "src/main/java").getAbsolutePath()));
105106
}
106107

108+
@Test
109+
public void project_with_java_files_not_in_src_should_not_be_collected() throws Exception {
110+
File baseDir = executeProject(
111+
"project-with-java-files-not-in-src",
112+
"sonar.maven.scanAll", "true");
113+
Set<String> actualListOfSources = extractSonarSources("target/dump.properties", baseDir.toPath());
114+
assertThat(actualListOfSources).containsExactlyInAnyOrder(
115+
"/pom.xml", "/src/main/java");
116+
}
117+
118+
@Test
119+
public void project_with_java_files_not_in_src_should_be_collected_when_user_define_binaries_and_libraries() throws Exception {
120+
File baseDir = executeProject(
121+
"project-with-java-files-not-in-src",
122+
"sonar.maven.scanAll", "true",
123+
"sonar.java.binaries", "target/classes",
124+
"sonar.java.libraries", "target/lib/logger.jar");
125+
Set<String> actualListOfSources = extractSonarSources("target/dump.properties", baseDir.toPath());
126+
assertThat(actualListOfSources).containsExactlyInAnyOrder(
127+
"/pom.xml", "/src/main/java", "/Hello.java", "/Hello.kt");
128+
}
129+
130+
@Test
131+
public void project_with_java_files_not_in_src_should_not_be_collected_when_user_define_only_binaries() throws Exception {
132+
File baseDir = executeProject(
133+
"project-with-java-files-not-in-src",
134+
"sonar.maven.scanAll", "true",
135+
"sonar.java.binaries", "target/classes");
136+
Set<String> actualListOfSources = extractSonarSources("target/dump.properties", baseDir.toPath());
137+
assertThat(actualListOfSources).containsExactlyInAnyOrder(
138+
"/pom.xml", "/src/main/java");
139+
}
140+
141+
@Test
142+
public void project_with_java_files_not_in_src_should_not_be_collected_when_user_define_only_libraries() throws Exception {
143+
File baseDir = executeProject(
144+
"project-with-java-files-not-in-src",
145+
"sonar.maven.scanAll", "true",
146+
"sonar.java.libraries", "target/lib/logger.jar");
147+
Set<String> actualListOfSources = extractSonarSources("target/dump.properties", baseDir.toPath());
148+
assertThat(actualListOfSources).containsExactlyInAnyOrder(
149+
"/pom.xml", "/src/main/java");
150+
}
151+
107152
// MSONAR-113
108153
@Test
109154
public void shouldExportSurefireReportsPath() throws Exception {
@@ -130,19 +175,7 @@ public void reuse_findbugs_exclusions_from_reporting() throws IOException, Excep
130175
@Test
131176
public void exclude_report_paths_from_scanAll() throws Exception {
132177
File projectBarDir = executeProject("project-with-external-reports", "sonar.maven.scanAll", "true");
133-
134-
String sources = readProps("target/dump.properties")
135-
.entrySet()
136-
.stream()
137-
.filter(e -> e.getKey().toString().equals("sonar.sources"))
138-
.map(Map.Entry::getValue)
139-
.findFirst()
140-
.orElse(null);
141-
142-
Set<String> actualListOfSources = Arrays.stream(sources.split(","))
143-
.map(file -> file.replace(projectBarDir.toString(), "").replace("\\", "/"))
144-
.collect(Collectors.toSet());
145-
178+
Set<String> actualListOfSources = extractSonarSources("target/dump.properties", projectBarDir.toPath());
146179
assertThat(actualListOfSources).containsExactlyInAnyOrder("/other.xml", "/pom.xml");
147180
}
148181

@@ -193,11 +226,11 @@ private File executeProject(String projectName, String... properties) throws Exc
193226
}
194227

195228
@SafeVarargs
196-
private final void assertPropsContains(MapEntry<String, String>... entries) throws FileNotFoundException, IOException {
229+
private final void assertPropsContains(MapEntry<String, String>... entries) throws IOException {
197230
assertThat(readProps("target/dump.properties")).contains(entries);
198231
}
199232

200-
private Map<String, String> readProps(String filePath) throws FileNotFoundException, IOException {
233+
private static Map<String, String> readProps(String filePath) throws IOException {
201234
FileInputStream fis = null;
202235
try {
203236
File dump = new File(filePath);
@@ -210,4 +243,17 @@ private Map<String, String> readProps(String filePath) throws FileNotFoundExcept
210243
}
211244
}
212245

246+
private static Set<String> extractSonarSources(String propertiesPath, Path projectBarDir) throws IOException {
247+
String sources = readProps(propertiesPath)
248+
.entrySet()
249+
.stream()
250+
.filter(e -> e.getKey().endsWith("sonar.sources"))
251+
.map(Map.Entry::getValue)
252+
.findFirst()
253+
.orElse(null);
254+
255+
return Arrays.stream(sources.split(","))
256+
.map(file -> file.replace(projectBarDir.toString(), "").replace("\\", "/"))
257+
.collect(Collectors.toSet());
258+
}
213259
}

src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperTest.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void scanAll_property_is_applied_by_default() throws MojoExecutionException {
165165
});
166166

167167
verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources.");
168-
verify(scannerBootstrapper, times(1)).collectAllSources(any());
168+
verify(scannerBootstrapper, times(1)).collectAllSources(any(), eq(false));
169169
}
170170

171171
@Test
@@ -179,7 +179,7 @@ void scanAll_property_is_not_applied_when_set_explicitly() throws MojoExecutionE
179179
});
180180

181181
verify(log, never()).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources.");
182-
verify(scannerBootstrapper, never()).collectAllSources(any());
182+
verify(scannerBootstrapper, never()).collectAllSources(any(), eq(false));
183183
}
184184

185185
@Test
@@ -194,7 +194,22 @@ void scanAll_property_is_applied_when_set_explicitly() throws MojoExecutionExcep
194194
});
195195

196196
verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources.");
197-
verify(scannerBootstrapper, times(1)).collectAllSources(any());
197+
verify(scannerBootstrapper, times(1)).collectAllSources(any(), eq(false));
198+
}
199+
200+
@Test
201+
void scanAll_should_also_collect_java_and_kotlin_sources_when_binaries_and_libraries_are_explicitly_set() throws MojoExecutionException {
202+
setSonarScannerScanAllAndBinariesAndLibraries();
203+
204+
verifyCollectedSources(sourceDirs -> {
205+
assertThat(sourceDirs).hasSize(3);
206+
assertThat(sourceDirs[0]).endsWith(Paths.get("src", "main", "java").toString());
207+
assertThat(sourceDirs[1]).endsWith(Paths.get("pom.xml").toString());
208+
assertThat(sourceDirs[2]).endsWith(Paths.get("src", "main", "resources", "index.js").toString());
209+
});
210+
211+
verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources.");
212+
verify(scannerBootstrapper, times(1)).collectAllSources(any(), eq(true));
198213
}
199214

200215
@Test
@@ -212,7 +227,7 @@ void should_not_collect_all_sources_when_sonar_sources_is_overridden() throws Mo
212227

213228
verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources.");
214229
verify(log, times(1)).warn("Parameter sonar.maven.scanAll is enabled but the scanner will not collect additional sources because sonar.sources has been overridden.");
215-
verify(scannerBootstrapper, never()).collectAllSources(any());
230+
verify(scannerBootstrapper, never()).collectAllSources(any(), eq(false));
216231
}
217232

218233
@Test
@@ -231,7 +246,7 @@ void should_not_collect_all_sources_when_sonar_tests_is_overridden() throws Mojo
231246

232247
verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources.");
233248
verify(log, times(1)).warn("Parameter sonar.maven.scanAll is enabled but the scanner will not collect additional sources because sonar.tests has been overridden.");
234-
verify(scannerBootstrapper, never()).collectAllSources(any());
249+
verify(scannerBootstrapper, never()).collectAllSources(any(), eq(false));
235250
}
236251

237252
@Test
@@ -334,6 +349,14 @@ private void setSonarScannerScanAllTo(String value) {
334349
when(session.getUserProperties()).thenReturn(withScanAllSet);
335350
}
336351

352+
private void setSonarScannerScanAllAndBinariesAndLibraries() {
353+
Properties withScanAllSet = new Properties();
354+
withScanAllSet.put(MavenScannerProperties.PROJECT_SCAN_ALL_SOURCES, "true");
355+
withScanAllSet.put(MavenProjectConverter.JAVA_PROJECT_MAIN_BINARY_DIRS, "target/classes");
356+
withScanAllSet.put(MavenProjectConverter.JAVA_PROJECT_MAIN_LIBRARIES, "target/lib/log.jar");
357+
when(session.getUserProperties()).thenReturn(withScanAllSet);
358+
}
359+
337360
private void verifyCollectedSources(Consumer<String[]> sourceDirsAssertions) throws MojoExecutionException {
338361
Map<String, String> collectedProperties = scannerBootstrapper.collectProperties();
339362
assertThat(collectedProperties).containsKey(ScanProperties.PROJECT_SOURCE_DIRS);

0 commit comments

Comments
 (0)