Skip to content

Commit 7e95b6d

Browse files
committed
[GR-17457] Add jt spotbugs and mx ruby_spotbugs to run more SpotBugs checks
PullRequest: truffleruby/1982
2 parents 7a5743c + 92dc95f commit 7e95b6d

File tree

83 files changed

+384
-705
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+384
-705
lines changed

mx.truffleruby/mx_truffleruby.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import mx
1414
import mx_sdk
1515
import mx_subst
16+
import mx_spotbugs
1617

1718
if 'RUBY_BENCHMARKS' in os.environ:
1819
import mx_truffleruby_benchmark # pylint: disable=unused-import
@@ -160,6 +161,14 @@ def ruby_testdownstream_sulong(args):
160161
jt('test', 'mri', '--all-sulong')
161162
jt('test', 'cexts')
162163

164+
def ruby_spotbugs(args):
165+
"""Run SpotBugs with custom options to detect more issues"""
166+
filters = join(root, 'mx.truffleruby', 'spotbugs-filters.xml')
167+
spotbugsArgs = ['-textui', '-low', '-longBugCodes', '-include', filters]
168+
if mx.is_interactive():
169+
spotbugsArgs.append('-progress')
170+
mx_spotbugs.spotbugs(args, spotbugsArgs)
171+
163172
def verify_ci(args):
164173
"""Verify CI configuration"""
165174
mx.verify_ci(args, mx.suite('truffle'), _suite, 'common.json')
@@ -247,5 +256,6 @@ def verify_ci(args):
247256
'ruby_testdownstream_aot': [ruby_testdownstream_aot, 'aot_bin'],
248257
'ruby_testdownstream_hello': [ruby_testdownstream_hello, ''],
249258
'ruby_testdownstream_sulong': [ruby_testdownstream_sulong, ''],
259+
'ruby_spotbugs': [ruby_spotbugs, ''],
250260
'verify-ci' : [verify_ci, '[options]'],
251261
})

mx.truffleruby/spotbugs-filters.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<FindBugsFilter>
3+
<Match>
4+
<Package name="~org\.truffleruby.*" />
5+
<Not>
6+
<Or>
7+
<!-- These are not worth fixing -->
8+
<Bug pattern="MS_PKGPROTECT" />
9+
<Bug pattern="MS_MUTABLE_ARRAY" />
10+
<Bug pattern="MS_MUTABLE_COLLECTION" />
11+
<Bug pattern="SF_SWITCH_NO_DEFAULT" />
12+
<Bug pattern="RI_REDUNDANT_INTERFACES" />
13+
<Bug pattern="EQ_COMPARETO_USE_OBJECT_EQUALS" />
14+
<Bug pattern="SE_BAD_FIELD" />
15+
<!-- Intentional -->
16+
<Bug pattern="BC_UNCONFIRMED_CAST" />
17+
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE" />
18+
<Bug pattern="DM_EXIT" />
19+
<Bug pattern="DM_GC" />
20+
<Bug pattern="EI_EXPOSE_REP" />
21+
<Bug pattern="EI_EXPOSE_REP2" />
22+
<Bug pattern="FE_FLOATING_POINT_EQUALITY" />
23+
<Bug pattern="NM_CLASS_NOT_EXCEPTION" />
24+
<Bug pattern="RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN" />
25+
<Bug pattern="BX_UNBOXING_IMMEDIATELY_REBOXED" /> <!-- used as a way to assert the type -->
26+
<Bug pattern="PZLA_PREFER_ZERO_LENGTH_ARRAYS" />
27+
</Or>
28+
</Not>
29+
</Match>
30+
</FindBugsFilter>

spec/truffle/interop/special_forms_spec.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,10 @@
189189
l.log.should include(["instantiate"])
190190
end
191191

192+
# Always include in the documentation, even when run on native
193+
desc = description['.class', :readMember, ['"class"'], 'when `foreign_object` is a `java.lang.Class`']
192194
guard -> { !TruffleRuby.native? } do
193-
it description['.class', :readMember, ['"class"'], 'when `foreign_object` is a `java.lang.Class`'] do
195+
it desc do
194196
Java.type('java.math.BigInteger').class.getName.should == 'java.math.BigInteger'
195197
end
196198
end

src/annotations/java/org/truffleruby/SuppressFBWarnings.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
import java.lang.annotation.Retention;
1313
import java.lang.annotation.RetentionPolicy;
1414

15-
/** Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings. */
15+
/** Used to suppress <a href="http://findbugs.sourceforge.net">SpotBugs</a> warnings. */
1616
@Retention(RetentionPolicy.CLASS)
1717
public @interface SuppressFBWarnings {
18-
/** The set of FindBugs <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
19-
* suppressed in annotated element. The value can be a bug category, kind or pattern. */
18+
/** The set of SpotBugs <a href="https://spotbugs.readthedocs.io/en/stable/bugDescriptions.html">warnings</a> that
19+
* are suppressed for the annotated element. The value can be a bug category, kind or pattern. */
2020
String[] value();
2121
}

src/annotations/java/org/truffleruby/language/Visibility.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,4 @@ public enum Visibility {
3131
PROTECTED,
3232
PRIVATE,
3333
MODULE_FUNCTION;
34-
35-
private static final Visibility[] VALUES = values();
36-
37-
public boolean isPublic() {
38-
return this == PUBLIC;
39-
}
40-
41-
public boolean isProtected() {
42-
return this == PROTECTED;
43-
}
44-
45-
public boolean isPrivate() {
46-
return this == PRIVATE;
47-
}
48-
49-
public boolean isModuleFunction() {
50-
return this == MODULE_FUNCTION;
51-
}
52-
53-
public static Visibility[] getValues() {
54-
return VALUES;
55-
}
5634
}

src/main/java/org/truffleruby/RubyContext.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,16 @@ public class RubyContext {
144144

145145
private static boolean preInitializeContexts = TruffleRuby.PRE_INITIALIZE_CONTEXTS;
146146

147+
private static boolean isPreInitializingContext() {
148+
boolean isPreInitializingContext = preInitializeContexts;
149+
preInitializeContexts = false; // Only the first context is pre-initialized
150+
return isPreInitializingContext;
151+
}
152+
147153
public RubyContext(RubyLanguage language, TruffleLanguage.Env env) {
148154
Metrics.printTime("before-context-constructor");
149155

150-
this.preInitializing = preInitializeContexts;
151-
RubyContext.preInitializeContexts = false; // Only the first context is pre-initialized
156+
this.preInitializing = isPreInitializingContext();
152157
this.preInitialized = preInitializing;
153158

154159
preInitializationManager = preInitializing ? new PreInitializationManager(this) : null;

src/main/java/org/truffleruby/RubyFileTypeDetector.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java.nio.charset.Charset;
1515
import java.nio.charset.StandardCharsets;
1616
import java.util.Locale;
17-
import java.util.function.BiConsumer;
1817
import java.util.regex.Pattern;
1918

2019
import org.jcodings.Encoding;
@@ -80,14 +79,11 @@ public Charset findEncoding(TruffleFile file) throws IOException {
8079
if (encodingCommentLine != null) {
8180
Rope encodingCommentRope = StringOperations.encodeRope(encodingCommentLine, UTF8Encoding.INSTANCE);
8281
Charset[] encodingHolder = new Charset[1];
83-
RubyLexer.parseMagicComment(encodingCommentRope, new BiConsumer<String, Rope>() {
84-
@Override
85-
public void accept(String name, Rope value) {
86-
if (RubyLexer.isMagicEncodingComment(name)) {
87-
Encoding encoding = EncodingManager.getEncoding(value);
88-
if (encoding != null) {
89-
encodingHolder[0] = encoding.getCharset();
90-
}
82+
RubyLexer.parseMagicComment(encodingCommentRope, (name, value) -> {
83+
if (RubyLexer.isMagicEncodingComment(name)) {
84+
Encoding encoding = EncodingManager.getEncoding(value);
85+
if (encoding != null) {
86+
encodingHolder[0] = encoding.getCharset();
9187
}
9288
}
9389
});

src/main/java/org/truffleruby/aot/TruffleRubySupport.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.regex.Matcher;
2727
import java.util.regex.Pattern;
2828

29+
import com.oracle.truffle.api.CompilerDirectives;
2930
import org.jcodings.Encoding;
3031
import org.jcodings.EncodingDB;
3132
import org.jcodings.util.ArrayReader;
@@ -73,12 +74,15 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
7374
try (InputStream is = ArrayReader.class.getResourceAsStream(entry)) {
7475
if (is != null) {
7576
byte[] buf = new byte[is.available()];
76-
new DataInputStream(is).readFully(buf);
77+
try (DataInputStream dataInputStream = new DataInputStream(is)) {
78+
dataInputStream.readFully(buf);
79+
}
7780
jcodingsTables.put(name, buf);
7881
} else {
79-
throw new Error("Unable to load Jcodings table " + name);
82+
throw CompilerDirectives.shouldNotReachHere("Unable to load Jcodings table " + name);
8083
}
8184
} catch (IOException e) {
85+
throw CompilerDirectives.shouldNotReachHere(e);
8286
}
8387
}
8488
return jcodingsTables;

src/main/java/org/truffleruby/cext/CExtNodes.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,11 +754,11 @@ protected boolean checkCallerVisibility(RubySymbol visibility) {
754754

755755
switch (visibility.getString()) {
756756
case "private":
757-
return callerVisibility.isPrivate();
757+
return callerVisibility == Visibility.PRIVATE;
758758
case "protected":
759-
return callerVisibility.isProtected();
759+
return callerVisibility == Visibility.PROTECTED;
760760
case "module_function":
761-
return callerVisibility.isModuleFunction();
761+
return callerVisibility == Visibility.MODULE_FUNCTION;
762762
default:
763763
throw CompilerDirectives.shouldNotReachHere();
764764
}

src/main/java/org/truffleruby/cext/ValueWrapperManager.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
import org.truffleruby.RubyContext;
1919
import org.truffleruby.RubyLanguage;
20+
import org.truffleruby.SuppressFBWarnings;
2021
import org.truffleruby.cext.ValueWrapperManagerFactory.AllocateHandleNodeGen;
2122
import org.truffleruby.cext.ValueWrapperManagerFactory.GetHandleBlockHolderNodeGen;
23+
import org.truffleruby.extra.ffi.Pointer;
2224
import org.truffleruby.language.NotProvided;
2325
import org.truffleruby.language.RubyBaseNode;
2426

@@ -32,6 +34,7 @@
3234
import com.oracle.truffle.api.library.ExportLibrary;
3335
import com.oracle.truffle.api.library.ExportMessage;
3436

37+
@SuppressFBWarnings("VO")
3538
public class ValueWrapperManager {
3639

3740
static final long UNSET_HANDLE = -2L;
@@ -232,7 +235,7 @@ public boolean isFull() {
232235
}
233236

234237
public long setHandleOnWrapper(ValueWrapper wrapper) {
235-
long handle = getBase() + count * 8;
238+
long handle = getBase() + count * Pointer.SIZE;
236239
wrapper.setHandle(handle, this);
237240
wrappers[count] = wrapper;
238241
count++;

0 commit comments

Comments
 (0)