Skip to content

Commit 636c118

Browse files
authored
Merge pull request #1328 from spotbugs/copilot/fix-integration-test-issue
Fix noClassOk: move -noClassOk flag before class directory args so SpotBugs recognizes it
2 parents 8a3b4a5 + 0bcf6f1 commit 636c118

File tree

5 files changed

+196
-15
lines changed

5 files changed

+196
-15
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#
2+
# Copyright 2005-2026 the original author or authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
invoker.goals = clean verify --no-transfer-progress
18+
19+
# The expected result of the build, possible values are "success" (default) and "failure"
20+
invoker.buildResult = success

src/it/noClassOk/pom.xml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2005-2026 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
https://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
22+
<modelVersion>4.0.0</modelVersion>
23+
24+
<!-- Parent is disabled on purpose
25+
<parent>
26+
<groupId>spotbugs-maven-plugin.it</groupId>
27+
<artifactId>common</artifactId>
28+
<version>testing</version>
29+
<relativePath>../common.xml</relativePath>
30+
</parent>
31+
-->
32+
33+
<groupId>spotbugs-maven-plugin.it</groupId>
34+
<artifactId>noClassOk</artifactId>
35+
<version>testing</version>
36+
37+
<name>noClassOk</name>
38+
39+
<url>https://spotbugs.github.io/spotbugs-maven-plugin/</url>
40+
41+
<properties>
42+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
43+
<project.build.resourceEncoding>UTF-8</project.build.resourceEncoding>
44+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
45+
46+
<!-- These two are used due to old compiler on maven 3.6.3 GHA build -->
47+
<maven.compiler.source>11</maven.compiler.source>
48+
<maven.compiler.target>11</maven.compiler.target>
49+
50+
<maven.compiler.release>11</maven.compiler.release>
51+
</properties>
52+
53+
<build>
54+
<plugins>
55+
<plugin>
56+
<groupId>org.apache.maven.plugins</groupId>
57+
<artifactId>maven-clean-plugin</artifactId>
58+
<version>@clean.plugin@</version>
59+
<configuration>
60+
<force>true</force>
61+
</configuration>
62+
</plugin>
63+
<plugin>
64+
<groupId>com.github.spotbugs</groupId>
65+
<artifactId>spotbugs-maven-plugin</artifactId>
66+
<version>@pom.version@</version>
67+
<configuration>
68+
<noClassOk>true</noClassOk>
69+
<debug>@spotbugsTestDebug@</debug>
70+
</configuration>
71+
<executions>
72+
<execution>
73+
<id>run-analysis</id>
74+
<phase>process-classes</phase>
75+
<goals>
76+
<goal>spotbugs</goal>
77+
</goals>
78+
</execution>
79+
</executions>
80+
</plugin>
81+
</plugins>
82+
</build>
83+
84+
</project>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# Copyright 2005-2026 the original author or authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
nothing=all

src/it/noClassOk/verify.groovy

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2005-2026 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import groovy.xml.XmlSlurper
17+
import groovy.xml.slurpersupport.GPathResult
18+
import groovy.xml.slurpersupport.NodeChild
19+
20+
import java.nio.file.Files
21+
import java.nio.file.Path
22+
23+
// Verify that spotbugsXml.xml was created - proving SpotBugs ran with noClassOk=true
24+
// even though the project has no Java class files (only resources)
25+
26+
Path spotbugsXml = basedir.toPath().resolve('target/spotbugsXml.xml')
27+
assert Files.exists(spotbugsXml) : 'spotbugsXml.xml should exist when noClassOk=true'
28+
29+
println '**********************************'
30+
println 'Checking Spotbugs Native XML file'
31+
println '**********************************'
32+
33+
XmlSlurper xmlSlurper = new XmlSlurper()
34+
xmlSlurper.setFeature('http://apache.org/xml/features/disallow-doctype-decl', true)
35+
xmlSlurper.setFeature('http://apache.org/xml/features/nonvalidating/load-external-dtd', false)
36+
37+
GPathResult path = xmlSlurper.parse(spotbugsXml.toFile())
38+
39+
List<NodeChild> allNodes = path.depthFirst().toList()
40+
int spotbugsXmlErrors = allNodes.count { NodeChild node -> node.name() == 'BugInstance' }
41+
println "BugInstance size is ${spotbugsXmlErrors}"
42+
43+
assert spotbugsXmlErrors == 0 : 'Expected 0 bugs when no class files exist'

src/main/groovy/org/codehaus/mojo/spotbugs/SpotBugsMojo.groovy

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -535,23 +535,31 @@ class SpotBugsMojo extends AbstractMavenReport implements SpotBugsPluginsTrait {
535535
}
536536

537537
if (classFilesDirectory.exists()) {
538-
try {
539-
canGenerate = Files.walk(classFilesDirectory.toPath())
540-
.anyMatch(containsSource)
541-
} catch (IOException e) {
542-
log.warn("Error searching class files: ${e.message}")
538+
if (noClassOk) {
539+
canGenerate = true
540+
} else {
541+
try {
542+
canGenerate = Files.walk(classFilesDirectory.toPath())
543+
.anyMatch(containsSource)
544+
} catch (IOException e) {
545+
log.warn("Error searching class files: ${e.message}")
546+
}
543547
}
544548
if (log.isDebugEnabled()) {
545549
log.debug("canGenerate Src is ${canGenerate}")
546550
}
547551
}
548552

549553
if (!canGenerate && testClassFilesDirectory.exists() && includeTests) {
550-
try {
551-
canGenerate = Files.walk(testClassFilesDirectory.toPath())
552-
.anyMatch(containsSource)
553-
} catch (IOException e) {
554-
log.warn("Error searching test class files: ${e.message}")
554+
if (noClassOk) {
555+
canGenerate = true
556+
} else {
557+
try {
558+
canGenerate = Files.walk(testClassFilesDirectory.toPath())
559+
.anyMatch(containsSource)
560+
} catch (IOException e) {
561+
log.warn("Error searching test class files: ${e.message}")
562+
}
555563
}
556564
if (log.isDebugEnabled()) {
557565
log.debug("canGenerate Test Src is ${canGenerate}")
@@ -1010,6 +1018,11 @@ class SpotBugsMojo extends AbstractMavenReport implements SpotBugsPluginsTrait {
10101018
args << String.valueOf(maxRank)
10111019
}
10121020

1021+
if (noClassOk) {
1022+
log.debug(" Adding 'noClassOk'")
1023+
args << '-noClassOk'
1024+
}
1025+
10131026
if (classFilesDirectory.isDirectory()) {
10141027
if (log.isDebugEnabled()) {
10151028
log.debug(' Adding to Source Directory -> ' + classFilesDirectory.absolutePath)
@@ -1024,11 +1037,6 @@ class SpotBugsMojo extends AbstractMavenReport implements SpotBugsPluginsTrait {
10241037
args << testClassFilesDirectory.absolutePath
10251038
}
10261039

1027-
if (noClassOk) {
1028-
log.debug(" Adding 'noClassOk'")
1029-
args << '-noClassOk'
1030-
}
1031-
10321040
return args
10331041
}
10341042

@@ -1284,6 +1292,15 @@ class SpotBugsMojo extends AbstractMavenReport implements SpotBugsPluginsTrait {
12841292
writer << xmlBuilder.bind { mkp.yield path }
12851293
} else {
12861294
log.info('No bugs found')
1295+
if (noClassOk) {
1296+
log.info('No class files to analyze; creating empty output due to noClassOk=true')
1297+
Charset effectiveEncodingForEmpty = outputEncoding ?: StandardCharsets.UTF_8
1298+
Files.createDirectories(outputFile.toPath().getParent())
1299+
String minimalXml = '<?xml version="1.0" encoding="' +
1300+
effectiveEncodingForEmpty.name().toLowerCase(Locale.ROOT) + '"?>' +
1301+
SpotBugsInfo.EOL + '<BugCollection></BugCollection>'
1302+
Files.write(outputFile.toPath(), minimalXml.getBytes(effectiveEncodingForEmpty))
1303+
}
12871304
}
12881305

12891306
// Do not delete file when running under debug mode

0 commit comments

Comments
 (0)