danger-spotbugs 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/spotbugs/entity/bug_instance.rb +6 -2
- data/lib/spotbugs/gem_version.rb +1 -1
- data/spec/entity/bug_instance_spec.rb +58 -10
- data/spec/fixtures/spotbugs_report.xml +126 -23
- data/spec/spotbugs_spec.rb +80 -32
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 703a32ef1e4e92cc32381f904f7956aa557f26f7b698d364680bf8e27f20c2e7
|
4
|
+
data.tar.gz: 4c920a3822f89c99a1694886657e18acdd88d742dcab98e83e906f66d52f5d48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c1063d298ebbf8d3a49466a6aeb16f9fa2c1fc272edb30b87662f8df5a8d633596413e8a7e2a97243d5e612d379d31b0be7fa51b4c67c74c7d45370a58e3639
|
7
|
+
data.tar.gz: 1cafc111f92c6c613a92fe2af927687188b56267f569f885049762484c253c5e6f0fd2c50674b7cc0415a60cccb7055b3a9406b37ea00c3c9a5da550d8a4a169
|
data/Gemfile.lock
CHANGED
@@ -26,7 +26,7 @@ class BugInstance
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def line
|
29
|
-
@line ||= bug_instance.xpath('SourceLine').attribute('start').
|
29
|
+
@line ||= get_value_safely(bug_instance.xpath('SourceLine').attribute('start'), 0).to_i
|
30
30
|
end
|
31
31
|
|
32
32
|
def description
|
@@ -36,7 +36,7 @@ class BugInstance
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def get_source_path(bug_instance)
|
39
|
-
bug_instance.xpath('SourceLine').attribute('sourcepath').
|
39
|
+
get_value_safely(bug_instance.xpath('SourceLine').attribute('sourcepath'), '').to_s
|
40
40
|
end
|
41
41
|
|
42
42
|
def get_absolute_path(source_path)
|
@@ -56,4 +56,8 @@ class BugInstance
|
|
56
56
|
def file_separator
|
57
57
|
File::ALT_SEPARATOR || File::SEPARATOR
|
58
58
|
end
|
59
|
+
|
60
|
+
def get_value_safely(array, default_value)
|
61
|
+
array.compact.empty? ? default_value : array.compact.first.value
|
62
|
+
end
|
59
63
|
end
|
data/lib/spotbugs/gem_version.rb
CHANGED
@@ -62,6 +62,54 @@ module Spotbugs
|
|
62
62
|
xml.xpath('//BugInstance')[1]
|
63
63
|
)
|
64
64
|
|
65
|
+
expect(bug_instance.rank).to eq(6)
|
66
|
+
expect(bug_instance.line).to eq(45)
|
67
|
+
expect(bug_instance.type).to eq(:warn)
|
68
|
+
expect(bug_instance.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
69
|
+
expect(bug_instance.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
70
|
+
expect(bug_instance.description).to eq('com.github.sample.model.Message.getProperties() may return null, but is declared @Nonnull')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should initialize with third bug instance' do
|
74
|
+
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
75
|
+
bug_instance = BugInstance.new(
|
76
|
+
'/Users/developer/project/sample/',
|
77
|
+
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
78
|
+
xml.xpath('//BugInstance')[2]
|
79
|
+
)
|
80
|
+
|
81
|
+
expect(bug_instance.rank).to eq(14)
|
82
|
+
expect(bug_instance.line).to eq(0)
|
83
|
+
expect(bug_instance.type).to eq(:warn)
|
84
|
+
expect(bug_instance.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
85
|
+
expect(bug_instance.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
86
|
+
expect(bug_instance.description).to eq('Class com.github.sample.model.Message defines non-transient non-serializable instance field conversation')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should initialize with fourth bug instance' do
|
90
|
+
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
91
|
+
bug_instance = BugInstance.new(
|
92
|
+
'/Users/developer/project/sample/',
|
93
|
+
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
94
|
+
xml.xpath('//BugInstance')[3]
|
95
|
+
)
|
96
|
+
|
97
|
+
expect(bug_instance.rank).to eq(14)
|
98
|
+
expect(bug_instance.line).to eq(0)
|
99
|
+
expect(bug_instance.type).to eq(:warn)
|
100
|
+
expect(bug_instance.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
101
|
+
expect(bug_instance.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
102
|
+
expect(bug_instance.description).to eq('Class com.github.sample.model.Message defines non-transient non-serializable instance field sender')
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should initialize with fifth bug instance' do
|
106
|
+
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
107
|
+
bug_instance = BugInstance.new(
|
108
|
+
'/Users/developer/project/sample/',
|
109
|
+
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
110
|
+
xml.xpath('//BugInstance')[4]
|
111
|
+
)
|
112
|
+
|
65
113
|
expect(bug_instance.rank).to eq(6)
|
66
114
|
expect(bug_instance.line).to eq(31)
|
67
115
|
expect(bug_instance.type).to eq(:warn)
|
@@ -70,12 +118,12 @@ module Spotbugs
|
|
70
118
|
expect(bug_instance.description).to eq('Possible null pointer dereference of Tools$Helper.string in com.github.sample.tools.Tools$Helper.setText(TextView)')
|
71
119
|
end
|
72
120
|
|
73
|
-
it 'should initialize with
|
121
|
+
it 'should initialize with sixth bug instance' do
|
74
122
|
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
75
123
|
bug_instance = BugInstance.new(
|
76
124
|
'/Users/developer/project/sample/',
|
77
125
|
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
78
|
-
xml.xpath('//BugInstance')[
|
126
|
+
xml.xpath('//BugInstance')[5]
|
79
127
|
)
|
80
128
|
|
81
129
|
expect(bug_instance.rank).to eq(8)
|
@@ -86,12 +134,12 @@ module Spotbugs
|
|
86
134
|
expect(bug_instance.description).to eq('Read of unwritten field title in com.github.sample.tools.Tools$Helper.setText(TextView)')
|
87
135
|
end
|
88
136
|
|
89
|
-
it 'should initialize with
|
137
|
+
it 'should initialize with seventh bug instance' do
|
90
138
|
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
91
139
|
bug_instance = BugInstance.new(
|
92
140
|
'/Users/developer/project/sample/',
|
93
141
|
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
94
|
-
xml.xpath('//BugInstance')[
|
142
|
+
xml.xpath('//BugInstance')[6]
|
95
143
|
)
|
96
144
|
|
97
145
|
expect(bug_instance.rank).to eq(18)
|
@@ -102,12 +150,12 @@ module Spotbugs
|
|
102
150
|
expect(bug_instance.description).to eq('Should com.github.sample.tools.Tools$Helper be a _static_ inner class?')
|
103
151
|
end
|
104
152
|
|
105
|
-
it 'should initialize with
|
153
|
+
it 'should initialize with eight bug instance' do
|
106
154
|
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
107
155
|
bug_instance = BugInstance.new(
|
108
156
|
'/Users/developer/project/sample/',
|
109
157
|
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
110
|
-
xml.xpath('//BugInstance')[
|
158
|
+
xml.xpath('//BugInstance')[7]
|
111
159
|
)
|
112
160
|
|
113
161
|
expect(bug_instance.rank).to eq(12)
|
@@ -118,12 +166,12 @@ module Spotbugs
|
|
118
166
|
expect(bug_instance.description).to eq('Unwritten field: com.github.sample.tools.Tools$Helper.title')
|
119
167
|
end
|
120
168
|
|
121
|
-
it 'should initialize with
|
169
|
+
it 'should initialize with nine bug instance' do
|
122
170
|
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
123
171
|
bug_instance = BugInstance.new(
|
124
172
|
'/Users/developer/project/sample/',
|
125
173
|
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
126
|
-
xml.xpath('//BugInstance')[
|
174
|
+
xml.xpath('//BugInstance')[8]
|
127
175
|
)
|
128
176
|
|
129
177
|
expect(bug_instance.rank).to eq(18)
|
@@ -134,12 +182,12 @@ module Spotbugs
|
|
134
182
|
expect(bug_instance.description).to eq('Should com.github.sample.tools.Tools$Other be a _static_ inner class?')
|
135
183
|
end
|
136
184
|
|
137
|
-
it 'should initialize with
|
185
|
+
it 'should initialize with ten bug instance' do
|
138
186
|
xml = Oga.parse_xml(File.open('spec/fixtures/spotbugs_report.xml'))
|
139
187
|
bug_instance = BugInstance.new(
|
140
188
|
'/Users/developer/project/sample/',
|
141
189
|
xml.xpath('//BugCollection//SrcDir').map(&:text),
|
142
|
-
xml.xpath('//BugInstance')[
|
190
|
+
xml.xpath('//BugInstance')[9]
|
143
191
|
)
|
144
192
|
|
145
193
|
expect(bug_instance.rank).to eq(5)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
|
3
|
-
<BugCollection version="4.1.1" sequence="0" timestamp="
|
3
|
+
<BugCollection version="4.1.1" sequence="0" timestamp="1620641501525" analysisTimestamp="1620641501684" release="unspecified">
|
4
4
|
<Project projectName="app (spotbugsRelease)">
|
5
5
|
<Jar>/Users/developer/project/sample/app/build/intermediates/javac/release/classes/com/github/sample/MainActivity.class</Jar>
|
6
6
|
<Jar>/Users/developer/project/sample/app/build/intermediates/javac/release/classes/com/github/sample/tools/Tools$Helper.class</Jar>
|
@@ -93,6 +93,82 @@
|
|
93
93
|
<Message>Known null at MainActivity.java:[line 29]</Message>
|
94
94
|
</SourceLine>
|
95
95
|
</BugInstance>
|
96
|
+
<BugInstance type="NP_NONNULL_RETURN_VIOLATION" priority="1" rank="6" abbrev="NP" category="CORRECTNESS" instanceHash="3fed666a46df9026e83022b1d37620b0" instanceOccurrenceNum="0" instanceOccurrenceMax="0" cweid="476">
|
97
|
+
<ShortMessage>Method may return null, but is declared @Nonnull</ShortMessage>
|
98
|
+
<LongMessage>com.github.sample.model.Message.getProperties() may return null, but is declared @Nonnull</LongMessage>
|
99
|
+
<Class classname="com.github.sample.model.Message" primary="true">
|
100
|
+
<SourceLine classname="com.github.sample.model.Message" start="20" end="50" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java">
|
101
|
+
<Message>At Message.java:[lines 20-50]</Message>
|
102
|
+
</SourceLine>
|
103
|
+
<Message>In class com.github.sample.model.Message</Message>
|
104
|
+
</Class>
|
105
|
+
<Method classname="com.github.sample.model.Message" name="getProperties" signature="()Ljava/lang/String;" isStatic="false" primary="true">
|
106
|
+
<SourceLine classname="com.github.sample.model.Message" start="45" end="45" startBytecode="0" endBytecode="46" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java"/>
|
107
|
+
<Message>In method com.github.sample.model.Message.getProperties()</Message>
|
108
|
+
</Method>
|
109
|
+
<Field classname="com.github.sample.model.Message" name="properties" signature="Ljava/lang/String;" isStatic="false" primary="true" role="FIELD_CONTAINS_VALUE">
|
110
|
+
<SourceLine classname="com.github.sample.model.Message" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java">
|
111
|
+
<Message>In Message.java</Message>
|
112
|
+
</SourceLine>
|
113
|
+
<Message>Value contained in com.github.sample.model.Message.properties</Message>
|
114
|
+
</Field>
|
115
|
+
<SourceLine classname="com.github.sample.model.Message" primary="true" start="45" end="45" startBytecode="4" endBytecode="4" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java" role="SOURCE_LINE_RETURNED">
|
116
|
+
<Message>Returned at Message.java:[line 45]</Message>
|
117
|
+
</SourceLine>
|
118
|
+
<SourceLine classname="com.github.sample.model.Message" start="45" end="45" startBytecode="4" endBytecode="4" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java" role="SOURCE_LINE_KNOWN_NULL">
|
119
|
+
<Message>Known null at Message.java:[line 45]</Message>
|
120
|
+
</SourceLine>
|
121
|
+
</BugInstance>
|
122
|
+
<BugInstance type="SE_BAD_FIELD" priority="1" rank="14" abbrev="Se" category="BAD_PRACTICE" instanceHash="44742cc905f428a65c6dd14ac2daae78" instanceOccurrenceNum="0" instanceOccurrenceMax="0">
|
123
|
+
<ShortMessage>Non-transient non-serializable instance field in serializable class</ShortMessage>
|
124
|
+
<LongMessage>Class com.github.sample.model.Message defines non-transient non-serializable instance field conversation</LongMessage>
|
125
|
+
<Class classname="com.github.sample.model.Message" primary="true">
|
126
|
+
<SourceLine classname="com.github.sample.model.Message" start="20" end="50" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java">
|
127
|
+
<Message>At Message.java:[lines 20-50]</Message>
|
128
|
+
</SourceLine>
|
129
|
+
<Message>In class com.github.sample.model.Message</Message>
|
130
|
+
</Class>
|
131
|
+
<Field classname="com.github.sample.model.Message" name="conversation" signature="Lcom/github/sample/model/Conversation;" isStatic="false" primary="true">
|
132
|
+
<SourceLine classname="com.github.sample.model.Message" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java">
|
133
|
+
<Message>In Message.java</Message>
|
134
|
+
</SourceLine>
|
135
|
+
<Message>Field com.github.sample.model.Message.conversation</Message>
|
136
|
+
</Field>
|
137
|
+
<Type descriptor="Lcom/github/sample/model/Conversation;" role="TYPE_FOUND">
|
138
|
+
<SourceLine classname="com.github.sample.model.Conversation" start="11" end="26" sourcefile="Conversation.java" sourcepath="com/github/sample/model/Conversation.java">
|
139
|
+
<Message>At Conversation.java:[lines 11-26]</Message>
|
140
|
+
</SourceLine>
|
141
|
+
<Message>Actual type com.github.sample.model.Conversation</Message>
|
142
|
+
</Type>
|
143
|
+
<SourceLine classname="com.github.sample.model.Message" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java" synthetic="true">
|
144
|
+
<Message>In Message.java</Message>
|
145
|
+
</SourceLine>
|
146
|
+
</BugInstance>
|
147
|
+
<BugInstance type="SE_BAD_FIELD" priority="1" rank="14" abbrev="Se" category="BAD_PRACTICE" instanceHash="5c07870442e74a0a719c0059c999090e" instanceOccurrenceNum="0" instanceOccurrenceMax="0">
|
148
|
+
<ShortMessage>Non-transient non-serializable instance field in serializable class</ShortMessage>
|
149
|
+
<LongMessage>Class com.github.sample.model.Message defines non-transient non-serializable instance field sender</LongMessage>
|
150
|
+
<Class classname="com.github.sample.model.Message" primary="true">
|
151
|
+
<SourceLine classname="com.github.sample.model.Message" start="20" end="50" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java">
|
152
|
+
<Message>At Message.java:[lines 20-50]</Message>
|
153
|
+
</SourceLine>
|
154
|
+
<Message>In class com.github.sample.model.Message</Message>
|
155
|
+
</Class>
|
156
|
+
<Field classname="com.github.sample.model.Message" name="sender" signature="Lcom/github/sample/model/User;" isStatic="false" primary="true">
|
157
|
+
<SourceLine classname="com.github.sample.model.Message" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java">
|
158
|
+
<Message>In Message.java</Message>
|
159
|
+
</SourceLine>
|
160
|
+
<Message>Field com.github.sample.model.Message.sender</Message>
|
161
|
+
</Field>
|
162
|
+
<Type descriptor="Lcom/github/sample/model/User;" role="TYPE_FOUND">
|
163
|
+
<SourceLine classname="com.github.sample.model.User" start="11" end="26" sourcefile="User.java" sourcepath="com/github/sample/model/User.java">
|
164
|
+
<Message>At User.java:[lines 11-26]</Message>
|
165
|
+
</SourceLine>
|
166
|
+
<Message>Actual type com.github.sample.model.User</Message>
|
167
|
+
</Type>
|
168
|
+
<SourceLine classname="com.github.sample.model.Message" sourcefile="Message.java" sourcepath="com/github/sample/model/Message.java" synthetic="true">
|
169
|
+
<Message>In Message.java</Message>
|
170
|
+
</SourceLine>
|
171
|
+
</BugInstance>
|
96
172
|
<BugInstance type="NP_NULL_ON_SOME_PATH" priority="1" rank="6" abbrev="NP" category="CORRECTNESS" instanceHash="36d97a1af3badcca6f42173c474917a6" instanceOccurrenceNum="0" instanceOccurrenceMax="0" cweid="476">
|
97
173
|
<ShortMessage>Possible null pointer dereference</ShortMessage>
|
98
174
|
<LongMessage>Possible null pointer dereference of Tools$Helper.string in com.github.sample.tools.Tools$Helper.setText(TextView)</LongMessage>
|
@@ -204,13 +280,16 @@
|
|
204
280
|
<Message>Value -1</Message>
|
205
281
|
</Int>
|
206
282
|
<Method classname="java.util.ArrayList" name="size" signature="()I" isStatic="false" role="METHOD_RETURN_VALUE_OF">
|
207
|
-
<SourceLine classname="java.util.ArrayList" start="
|
283
|
+
<SourceLine classname="java.util.ArrayList" start="285" end="285" startBytecode="0" endBytecode="64" sourcefile="ArrayList.java" sourcepath="java/util/ArrayList.java"/>
|
208
284
|
<Message>Return value of java.util.ArrayList.size() of type int</Message>
|
209
285
|
</Method>
|
210
286
|
<SourceLine classname="com.github.sample.view.ConversationAdapter" primary="true" start="32" end="32" startBytecode="5" endBytecode="5" sourcefile="ConversationAdapter.java" sourcepath="com/github/sample/view/ConversationAdapter.java">
|
211
287
|
<Message>At ConversationAdapter.java:[line 32]</Message>
|
212
288
|
</SourceLine>
|
213
289
|
</BugInstance>
|
290
|
+
<BugCategory category="BAD_PRACTICE">
|
291
|
+
<Description>Bad practice</Description>
|
292
|
+
</BugCategory>
|
214
293
|
<BugCategory category="CORRECTNESS">
|
215
294
|
<Description>Correctness</Description>
|
216
295
|
</BugCategory>
|
@@ -230,6 +309,17 @@ the null pointer exception can't ever be executed; deciding that is beyond the a
|
|
230
309
|
|
231
310
|
]]></Details>
|
232
311
|
</BugPattern>
|
312
|
+
<BugPattern type="NP_NONNULL_RETURN_VIOLATION" abbrev="NP" category="CORRECTNESS">
|
313
|
+
<ShortDescription>Method may return null, but is declared @Nonnull</ShortDescription>
|
314
|
+
<Details><![CDATA[
|
315
|
+
|
316
|
+
<p>
|
317
|
+
This method may return a null value, but the method (or a superclass method
|
318
|
+
which it overrides) is declared to return @Nonnull.
|
319
|
+
</p>
|
320
|
+
|
321
|
+
]]></Details>
|
322
|
+
</BugPattern>
|
233
323
|
<BugPattern type="UWF_UNWRITTEN_FIELD" abbrev="UwF" category="CORRECTNESS">
|
234
324
|
<ShortDescription>Unwritten field</ShortDescription>
|
235
325
|
<Details><![CDATA[
|
@@ -263,6 +353,19 @@ dereferencing this value will generate a null pointer exception.
|
|
263
353
|
|
264
354
|
]]></Details>
|
265
355
|
</BugPattern>
|
356
|
+
<BugPattern type="SE_BAD_FIELD" abbrev="Se" category="BAD_PRACTICE">
|
357
|
+
<ShortDescription>Non-transient non-serializable instance field in serializable class</ShortDescription>
|
358
|
+
<Details><![CDATA[
|
359
|
+
|
360
|
+
<p> This Serializable class defines a non-primitive instance field which is neither transient,
|
361
|
+
Serializable, or <code>java.lang.Object</code>, and does not appear to implement
|
362
|
+
the <code>Externalizable</code> interface or the
|
363
|
+
<code>readObject()</code> and <code>writeObject()</code> methods.
|
364
|
+
Objects of this class will not be deserialized correctly if a non-Serializable
|
365
|
+
object is stored in this field.</p>
|
366
|
+
|
367
|
+
]]></Details>
|
368
|
+
</BugPattern>
|
266
369
|
<BugPattern type="INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE" abbrev="INT" category="CORRECTNESS">
|
267
370
|
<ShortDescription>Bad comparison of nonnegative value with negative constant or zero</ShortDescription>
|
268
371
|
<Details><![CDATA[
|
@@ -275,6 +378,9 @@ dereferencing this value will generate a null pointer exception.
|
|
275
378
|
<BugCode abbrev="NP" cweid="476">
|
276
379
|
<Description>Null pointer dereference</Description>
|
277
380
|
</BugCode>
|
381
|
+
<BugCode abbrev="Se">
|
382
|
+
<Description>Incorrect definition of Serializable class</Description>
|
383
|
+
</BugCode>
|
278
384
|
<BugCode abbrev="UwF">
|
279
385
|
<Description>Unwritten field</Description>
|
280
386
|
</BugCode>
|
@@ -290,11 +396,11 @@ dereferencing this value will generate a null pointer exception.
|
|
290
396
|
<MissingClass>android.view.View</MissingClass>
|
291
397
|
<MissingClass>android.widget.TextView</MissingClass>
|
292
398
|
</Errors>
|
293
|
-
<FindBugsSummary timestamp="Mon,
|
294
|
-
<FileStats path="com/github/sample/BuildConfig.java" bugCount="0" size="
|
399
|
+
<FindBugsSummary timestamp="Mon, 10 May 2021 12:11:41 +0200" total_classes="14" referenced_classes="232" total_bugs="10" total_size="176" num_packages="4" java_version="11.0.10" vm_version="11.0.10+9" cpu_seconds="7.96" clock_seconds="3.13" peak_mbytes="245.68" alloc_mbytes="512.00" gc_seconds="0.03" priority_2="4" priority_1="6">
|
400
|
+
<FileStats path="com/github/sample/BuildConfig.java" bugCount="0" size="8"/>
|
295
401
|
<FileStats path="com/github/sample/MainActivity.java" bugCount="1" size="23" bugHash="3d4de8c5d2e5bc77cb5db28779c6c525"/>
|
296
402
|
<FileStats path="com/github/sample/model/Conversation.java" bugCount="0" size="16"/>
|
297
|
-
<FileStats path="com/github/sample/model/Message.java" bugCount="
|
403
|
+
<FileStats path="com/github/sample/model/Message.java" bugCount="3" size="26" bugHash="d95b4d13e0ff01bd6f699166cd212709"/>
|
298
404
|
<FileStats path="com/github/sample/model/Type.java" bugCount="0" size="11"/>
|
299
405
|
<FileStats path="com/github/sample/model/User.java" bugCount="0" size="16"/>
|
300
406
|
<FileStats path="com/github/sample/tools/Tools.java" bugCount="5" size="25" bugHash="f4054acc9c26c5455b8a4dbd032c7b07"/>
|
@@ -302,14 +408,14 @@ dereferencing this value will generate a null pointer exception.
|
|
302
408
|
<FileStats path="com/github/sample/view/ConversationClickListener.java" bugCount="0" size="2"/>
|
303
409
|
<FileStats path="com/github/sample/view/ConversationViewHolder.java" bugCount="0" size="15"/>
|
304
410
|
<FileStats path="com/github/sample/view/MainViewModel.java" bugCount="0" size="15"/>
|
305
|
-
<PackageStats package="com.github.sample" total_bugs="1" total_types="3" total_size="
|
306
|
-
<ClassStats class="com.github.sample.BuildConfig" sourceFile="BuildConfig.java" interface="false" size="
|
411
|
+
<PackageStats package="com.github.sample" total_bugs="1" total_types="3" total_size="31" priority_1="1">
|
412
|
+
<ClassStats class="com.github.sample.BuildConfig" sourceFile="BuildConfig.java" interface="false" size="8" bugs="0"/>
|
307
413
|
<ClassStats class="com.github.sample.MainActivity" sourceFile="MainActivity.java" interface="false" size="16" bugs="1" priority_1="1"/>
|
308
414
|
<ClassStats class="com.github.sample.MainActivity$1" sourceFile="MainActivity.java" interface="false" size="7" bugs="0"/>
|
309
415
|
</PackageStats>
|
310
|
-
<PackageStats package="com.github.sample.model" total_bugs="
|
416
|
+
<PackageStats package="com.github.sample.model" total_bugs="3" total_types="4" total_size="69" priority_1="3">
|
311
417
|
<ClassStats class="com.github.sample.model.Conversation" sourceFile="Conversation.java" interface="false" size="16" bugs="0"/>
|
312
|
-
<ClassStats class="com.github.sample.model.Message" sourceFile="Message.java" interface="false" size="
|
418
|
+
<ClassStats class="com.github.sample.model.Message" sourceFile="Message.java" interface="false" size="26" bugs="3" priority_1="3"/>
|
313
419
|
<ClassStats class="com.github.sample.model.Type" sourceFile="Type.java" interface="false" size="11" bugs="0"/>
|
314
420
|
<ClassStats class="com.github.sample.model.User" sourceFile="User.java" interface="false" size="16" bugs="0"/>
|
315
421
|
</PackageStats>
|
@@ -325,20 +431,17 @@ dereferencing this value will generate a null pointer exception.
|
|
325
431
|
<ClassStats class="com.github.sample.view.MainViewModel" sourceFile="MainViewModel.java" interface="false" size="15" bugs="0"/>
|
326
432
|
</PackageStats>
|
327
433
|
<FindBugsProfile>
|
328
|
-
<ClassProfile name="edu.umd.cs.findbugs.classfile.engine.ClassInfoAnalysisEngine" totalMilliseconds="
|
329
|
-
<ClassProfile name="edu.umd.cs.findbugs.detect.
|
330
|
-
<ClassProfile name="edu.umd.cs.findbugs.detect.
|
331
|
-
<ClassProfile name="edu.umd.cs.findbugs.classfile.engine.
|
332
|
-
<ClassProfile name="edu.umd.cs.findbugs.
|
333
|
-
<ClassProfile name="edu.umd.cs.findbugs.
|
334
|
-
<ClassProfile name="edu.umd.cs.findbugs.detect.
|
335
|
-
<ClassProfile name="edu.umd.cs.findbugs.classfile.engine.
|
336
|
-
<ClassProfile name="edu.umd.cs.findbugs.detect.
|
337
|
-
<ClassProfile name="edu.umd.cs.findbugs.
|
338
|
-
<ClassProfile name="edu.umd.cs.findbugs.detect.BuildObligationPolicyDatabase" totalMilliseconds="
|
339
|
-
<ClassProfile name="edu.umd.cs.findbugs.util.TopologicalSort" totalMilliseconds="46" invocations="903" avgMicrosecondsPerInvocation="51" maxMicrosecondsPerInvocation="1384" standardDeviationMicrosecondsPerInvocation="108"/>
|
340
|
-
<ClassProfile name="edu.umd.cs.findbugs.detect.FunctionsThatMightBeMistakenForProcedures" totalMilliseconds="39" invocations="231" avgMicrosecondsPerInvocation="172" maxMicrosecondsPerInvocation="3428" standardDeviationMicrosecondsPerInvocation="398"/>
|
341
|
-
<ClassProfile name="edu.umd.cs.findbugs.detect.OverridingEqualsNotSymmetrical" totalMilliseconds="38" invocations="231" avgMicrosecondsPerInvocation="167" maxMicrosecondsPerInvocation="9114" standardDeviationMicrosecondsPerInvocation="640"/>
|
434
|
+
<ClassProfile name="edu.umd.cs.findbugs.classfile.engine.ClassInfoAnalysisEngine" totalMilliseconds="626" invocations="1115" avgMicrosecondsPerInvocation="562" maxMicrosecondsPerInvocation="20203" standardDeviationMicrosecondsPerInvocation="1376"/>
|
435
|
+
<ClassProfile name="edu.umd.cs.findbugs.detect.FieldItemSummary" totalMilliseconds="257" invocations="232" avgMicrosecondsPerInvocation="1110" maxMicrosecondsPerInvocation="14526" standardDeviationMicrosecondsPerInvocation="2404"/>
|
436
|
+
<ClassProfile name="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods" totalMilliseconds="248" invocations="232" avgMicrosecondsPerInvocation="1072" maxMicrosecondsPerInvocation="17254" standardDeviationMicrosecondsPerInvocation="2383"/>
|
437
|
+
<ClassProfile name="edu.umd.cs.findbugs.classfile.engine.ClassDataAnalysisEngine" totalMilliseconds="160" invocations="1120" avgMicrosecondsPerInvocation="143" maxMicrosecondsPerInvocation="6404" standardDeviationMicrosecondsPerInvocation="278"/>
|
438
|
+
<ClassProfile name="edu.umd.cs.findbugs.OpcodeStack$JumpInfoFactory" totalMilliseconds="123" invocations="365" avgMicrosecondsPerInvocation="339" maxMicrosecondsPerInvocation="5431" standardDeviationMicrosecondsPerInvocation="526"/>
|
439
|
+
<ClassProfile name="edu.umd.cs.findbugs.detect.NoteDirectlyRelevantTypeQualifiers" totalMilliseconds="108" invocations="232" avgMicrosecondsPerInvocation="469" maxMicrosecondsPerInvocation="8119" standardDeviationMicrosecondsPerInvocation="1064"/>
|
440
|
+
<ClassProfile name="edu.umd.cs.findbugs.detect.CalledMethods" totalMilliseconds="96" invocations="232" avgMicrosecondsPerInvocation="417" maxMicrosecondsPerInvocation="9079" standardDeviationMicrosecondsPerInvocation="1138"/>
|
441
|
+
<ClassProfile name="edu.umd.cs.findbugs.classfile.engine.bcel.JavaClassAnalysisEngine" totalMilliseconds="81" invocations="294" avgMicrosecondsPerInvocation="278" maxMicrosecondsPerInvocation="19521" standardDeviationMicrosecondsPerInvocation="1327"/>
|
442
|
+
<ClassProfile name="edu.umd.cs.findbugs.detect.FunctionsThatMightBeMistakenForProcedures" totalMilliseconds="70" invocations="232" avgMicrosecondsPerInvocation="305" maxMicrosecondsPerInvocation="16789" standardDeviationMicrosecondsPerInvocation="1224"/>
|
443
|
+
<ClassProfile name="edu.umd.cs.findbugs.util.TopologicalSort" totalMilliseconds="70" invocations="940" avgMicrosecondsPerInvocation="75" maxMicrosecondsPerInvocation="2091" standardDeviationMicrosecondsPerInvocation="156"/>
|
444
|
+
<ClassProfile name="edu.umd.cs.findbugs.detect.BuildObligationPolicyDatabase" totalMilliseconds="56" invocations="232" avgMicrosecondsPerInvocation="244" maxMicrosecondsPerInvocation="4025" standardDeviationMicrosecondsPerInvocation="446"/>
|
342
445
|
</FindBugsProfile>
|
343
446
|
</FindBugsSummary>
|
344
447
|
<ClassFeatures></ClassFeatures>
|
data/spec/spotbugs_spec.rb
CHANGED
@@ -58,7 +58,7 @@ module Danger
|
|
58
58
|
|
59
59
|
spotbugs_issues = @spotbugs.report
|
60
60
|
expect(spotbugs_issues).not_to be_nil
|
61
|
-
expect(spotbugs_issues.length).to be(
|
61
|
+
expect(spotbugs_issues.length).to be(10)
|
62
62
|
|
63
63
|
spotbugs_issue1 = spotbugs_issues[0]
|
64
64
|
expect(spotbugs_issue1.rank).to eq(6)
|
@@ -70,51 +70,75 @@ module Danger
|
|
70
70
|
|
71
71
|
spotbugs_issue2 = spotbugs_issues[1]
|
72
72
|
expect(spotbugs_issue2.rank).to eq(6)
|
73
|
-
expect(spotbugs_issue2.line).to eq(
|
73
|
+
expect(spotbugs_issue2.line).to eq(45)
|
74
74
|
expect(spotbugs_issue2.type).to eq(:warn)
|
75
|
-
expect(spotbugs_issue2.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/
|
76
|
-
expect(spotbugs_issue2.relative_path).to eq('app/src/main/java/com/github/sample/
|
77
|
-
expect(spotbugs_issue2.description).to eq('
|
75
|
+
expect(spotbugs_issue2.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
76
|
+
expect(spotbugs_issue2.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
77
|
+
expect(spotbugs_issue2.description).to eq('com.github.sample.model.Message.getProperties() may return null, but is declared @Nonnull')
|
78
78
|
|
79
79
|
spotbugs_issue3 = spotbugs_issues[2]
|
80
|
-
expect(spotbugs_issue3.rank).to eq(
|
81
|
-
expect(spotbugs_issue3.line).to eq(
|
80
|
+
expect(spotbugs_issue3.rank).to eq(14)
|
81
|
+
expect(spotbugs_issue3.line).to eq(0)
|
82
82
|
expect(spotbugs_issue3.type).to eq(:warn)
|
83
|
-
expect(spotbugs_issue3.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/
|
84
|
-
expect(spotbugs_issue3.relative_path).to eq('app/src/main/java/com/github/sample/
|
85
|
-
expect(spotbugs_issue3.description).to eq('
|
83
|
+
expect(spotbugs_issue3.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
84
|
+
expect(spotbugs_issue3.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
85
|
+
expect(spotbugs_issue3.description).to eq('Class com.github.sample.model.Message defines non-transient non-serializable instance field conversation')
|
86
86
|
|
87
87
|
spotbugs_issue4 = spotbugs_issues[3]
|
88
|
-
expect(spotbugs_issue4.rank).to eq(
|
89
|
-
expect(spotbugs_issue4.line).to eq(
|
88
|
+
expect(spotbugs_issue4.rank).to eq(14)
|
89
|
+
expect(spotbugs_issue4.line).to eq(0)
|
90
90
|
expect(spotbugs_issue4.type).to eq(:warn)
|
91
|
-
expect(spotbugs_issue4.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/
|
92
|
-
expect(spotbugs_issue4.relative_path).to eq('app/src/main/java/com/github/sample/
|
93
|
-
expect(spotbugs_issue4.description).to eq('
|
91
|
+
expect(spotbugs_issue4.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
92
|
+
expect(spotbugs_issue4.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
93
|
+
expect(spotbugs_issue4.description).to eq('Class com.github.sample.model.Message defines non-transient non-serializable instance field sender')
|
94
94
|
|
95
95
|
spotbugs_issue5 = spotbugs_issues[4]
|
96
|
-
expect(spotbugs_issue5.rank).to eq(
|
97
|
-
expect(spotbugs_issue5.line).to eq(
|
96
|
+
expect(spotbugs_issue5.rank).to eq(6)
|
97
|
+
expect(spotbugs_issue5.line).to eq(31)
|
98
98
|
expect(spotbugs_issue5.type).to eq(:warn)
|
99
99
|
expect(spotbugs_issue5.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/tools/Tools.java')
|
100
100
|
expect(spotbugs_issue5.relative_path).to eq('app/src/main/java/com/github/sample/tools/Tools.java')
|
101
|
-
expect(spotbugs_issue5.description).to eq('
|
101
|
+
expect(spotbugs_issue5.description).to eq('Possible null pointer dereference of Tools$Helper.string in com.github.sample.tools.Tools$Helper.setText(TextView)')
|
102
102
|
|
103
103
|
spotbugs_issue6 = spotbugs_issues[5]
|
104
|
-
expect(spotbugs_issue6.rank).to eq(
|
105
|
-
expect(spotbugs_issue6.line).to eq(
|
104
|
+
expect(spotbugs_issue6.rank).to eq(8)
|
105
|
+
expect(spotbugs_issue6.line).to eq(32)
|
106
106
|
expect(spotbugs_issue6.type).to eq(:warn)
|
107
107
|
expect(spotbugs_issue6.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/tools/Tools.java')
|
108
108
|
expect(spotbugs_issue6.relative_path).to eq('app/src/main/java/com/github/sample/tools/Tools.java')
|
109
|
-
expect(spotbugs_issue6.description).to eq('
|
109
|
+
expect(spotbugs_issue6.description).to eq('Read of unwritten field title in com.github.sample.tools.Tools$Helper.setText(TextView)')
|
110
110
|
|
111
111
|
spotbugs_issue7 = spotbugs_issues[6]
|
112
|
-
expect(spotbugs_issue7.rank).to eq(
|
113
|
-
expect(spotbugs_issue7.line).to eq(
|
112
|
+
expect(spotbugs_issue7.rank).to eq(18)
|
113
|
+
expect(spotbugs_issue7.line).to eq(23)
|
114
114
|
expect(spotbugs_issue7.type).to eq(:warn)
|
115
|
-
expect(spotbugs_issue7.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/
|
116
|
-
expect(spotbugs_issue7.relative_path).to eq('app/src/main/java/com/github/sample/
|
117
|
-
expect(spotbugs_issue7.description).to eq('
|
115
|
+
expect(spotbugs_issue7.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/tools/Tools.java')
|
116
|
+
expect(spotbugs_issue7.relative_path).to eq('app/src/main/java/com/github/sample/tools/Tools.java')
|
117
|
+
expect(spotbugs_issue7.description).to eq('Should com.github.sample.tools.Tools$Helper be a _static_ inner class?')
|
118
|
+
|
119
|
+
spotbugs_issue8 = spotbugs_issues[7]
|
120
|
+
expect(spotbugs_issue8.rank).to eq(12)
|
121
|
+
expect(spotbugs_issue8.line).to eq(32)
|
122
|
+
expect(spotbugs_issue8.type).to eq(:warn)
|
123
|
+
expect(spotbugs_issue8.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/tools/Tools.java')
|
124
|
+
expect(spotbugs_issue8.relative_path).to eq('app/src/main/java/com/github/sample/tools/Tools.java')
|
125
|
+
expect(spotbugs_issue8.description).to eq('Unwritten field: com.github.sample.tools.Tools$Helper.title')
|
126
|
+
|
127
|
+
spotbugs_issue9 = spotbugs_issues[8]
|
128
|
+
expect(spotbugs_issue9.rank).to eq(18)
|
129
|
+
expect(spotbugs_issue9.line).to eq(15)
|
130
|
+
expect(spotbugs_issue9.type).to eq(:warn)
|
131
|
+
expect(spotbugs_issue9.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/tools/Tools.java')
|
132
|
+
expect(spotbugs_issue9.relative_path).to eq('app/src/main/java/com/github/sample/tools/Tools.java')
|
133
|
+
expect(spotbugs_issue9.description).to eq('Should com.github.sample.tools.Tools$Other be a _static_ inner class?')
|
134
|
+
|
135
|
+
spotbugs_issue10 = spotbugs_issues[9]
|
136
|
+
expect(spotbugs_issue10.rank).to eq(5)
|
137
|
+
expect(spotbugs_issue10.line).to eq(32)
|
138
|
+
expect(spotbugs_issue10.type).to eq(:warn)
|
139
|
+
expect(spotbugs_issue10.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/view/ConversationAdapter.java')
|
140
|
+
expect(spotbugs_issue10.relative_path).to eq('app/src/main/java/com/github/sample/view/ConversationAdapter.java')
|
141
|
+
expect(spotbugs_issue10.description).to eq('Bad comparison of nonnegative value with -1 in com.github.sample.view.ConversationAdapter.setConversations(ArrayList)')
|
118
142
|
end
|
119
143
|
|
120
144
|
it 'Report with report file not in target files' do
|
@@ -133,7 +157,7 @@ module Danger
|
|
133
157
|
|
134
158
|
spotbugs_issues = @spotbugs.report
|
135
159
|
expect(spotbugs_issues).not_to be_nil
|
136
|
-
expect(spotbugs_issues.length).to be(
|
160
|
+
expect(spotbugs_issues.length).to be(5)
|
137
161
|
|
138
162
|
spotbugs_issue1 = spotbugs_issues[0]
|
139
163
|
expect(spotbugs_issue1.rank).to eq(6)
|
@@ -144,12 +168,36 @@ module Danger
|
|
144
168
|
expect(spotbugs_issue1.description).to eq('Possible null pointer dereference of MainActivity.conversationAdapter in com.github.sample.MainActivity.onCreate(Bundle)')
|
145
169
|
|
146
170
|
spotbugs_issue2 = spotbugs_issues[1]
|
147
|
-
expect(spotbugs_issue2.rank).to eq(
|
148
|
-
expect(spotbugs_issue2.line).to eq(
|
171
|
+
expect(spotbugs_issue2.rank).to eq(6)
|
172
|
+
expect(spotbugs_issue2.line).to eq(45)
|
149
173
|
expect(spotbugs_issue2.type).to eq(:warn)
|
150
|
-
expect(spotbugs_issue2.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/
|
151
|
-
expect(spotbugs_issue2.relative_path).to eq('app/src/main/java/com/github/sample/
|
152
|
-
expect(spotbugs_issue2.description).to eq('
|
174
|
+
expect(spotbugs_issue2.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
175
|
+
expect(spotbugs_issue2.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
176
|
+
expect(spotbugs_issue2.description).to eq('com.github.sample.model.Message.getProperties() may return null, but is declared @Nonnull')
|
177
|
+
|
178
|
+
spotbugs_issue3 = spotbugs_issues[2]
|
179
|
+
expect(spotbugs_issue3.rank).to eq(14)
|
180
|
+
expect(spotbugs_issue3.line).to eq(0)
|
181
|
+
expect(spotbugs_issue3.type).to eq(:warn)
|
182
|
+
expect(spotbugs_issue3.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
183
|
+
expect(spotbugs_issue3.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
184
|
+
expect(spotbugs_issue3.description).to eq('Class com.github.sample.model.Message defines non-transient non-serializable instance field conversation')
|
185
|
+
|
186
|
+
spotbugs_issue4 = spotbugs_issues[3]
|
187
|
+
expect(spotbugs_issue4.rank).to eq(14)
|
188
|
+
expect(spotbugs_issue4.line).to eq(0)
|
189
|
+
expect(spotbugs_issue4.type).to eq(:warn)
|
190
|
+
expect(spotbugs_issue4.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/model/Message.java')
|
191
|
+
expect(spotbugs_issue4.relative_path).to eq('app/src/main/java/com/github/sample/model/Message.java')
|
192
|
+
expect(spotbugs_issue4.description).to eq('Class com.github.sample.model.Message defines non-transient non-serializable instance field sender')
|
193
|
+
|
194
|
+
spotbugs_issue5 = spotbugs_issues[4]
|
195
|
+
expect(spotbugs_issue5.rank).to eq(5)
|
196
|
+
expect(spotbugs_issue5.line).to eq(32)
|
197
|
+
expect(spotbugs_issue5.type).to eq(:warn)
|
198
|
+
expect(spotbugs_issue5.absolute_path).to eq('/Users/developer/project/sample/app/src/main/java/com/github/sample/view/ConversationAdapter.java')
|
199
|
+
expect(spotbugs_issue5.relative_path).to eq('app/src/main/java/com/github/sample/view/ConversationAdapter.java')
|
200
|
+
expect(spotbugs_issue5.description).to eq('Bad comparison of nonnegative value with -1 in com.github.sample.view.ConversationAdapter.setConversations(ArrayList)')
|
153
201
|
end
|
154
202
|
|
155
203
|
it 'Report without Gradle' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: danger-spotbugs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mathieu Rul
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: danger-plugin-api
|