Repository navigation
Expand file tree
/
Copy pathStaticMethodHidingCheckSample.java
More file actions
437 lines (336 loc) · 11.2 KB
/
Copy pathStaticMethodHidingCheckSample.java
File metadata and controls
437 lines (336 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
package checks;
import com.google.errorprone.annotations.DoNotCall;
import com.google.errorprone.annotations.InlineMe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jetbrains.annotations.ApiStatus;
class StaticMethodHidingCheckSample {
// --- Basic hiding ---
static class Animal {
static void describe() {
}
}
static class Dog extends Animal {
static void describe() { // Noncompliant {{Rename this method; it hides "describe" in "Animal".}}
// ^^^^^^^^
}
}
// --- Hiding with parameters ---
static class Formatter {
static String format(String input) {
return input;
}
static String format(String input, int width) {
return input;
}
}
static class CustomFormatter extends Formatter {
static String format(String input) { // Noncompliant {{Rename this method; it hides "format" in "Formatter".}}
return input.trim();
}
static String format(String input, int width) { // Noncompliant {{Rename this method; it hides "format" in "Formatter".}}
return input.trim();
}
}
// --- Deep hierarchy hiding ---
static class Base {
static void process() {
}
}
static class Middle extends Base {
static void process() { // Noncompliant {{Rename this method; it hides "process" in "Base".}}
}
}
static class Leaf extends Middle {
static void process() { // Noncompliant {{Rename this method; it hides "process" in "Middle".}}
}
}
// --- Compliant: different parameter types (overloading, not hiding) ---
static class ParentA {
static void compute(int x) {
}
}
static class ChildA extends ParentA {
static void compute(String x) { // Compliant - different param type
}
}
// --- Compliant: different parameter count ---
static class ParentB {
static void compute(int x) {
}
}
static class ChildB extends ParentB {
static void compute(int x, int y) { // Compliant - different param count
}
}
// --- Compliant: instance method overriding ---
static class ParentC {
void display() {
}
}
static class ChildC extends ParentC {
@Override
void display() { // Compliant - instance method override
}
}
// --- Compliant: no inheritance ---
static class Unrelated1 {
static void helper() {
}
}
static class Unrelated2 {
static void helper() { // Compliant - no inheritance relationship
}
}
// --- Compliant: renamed methods ---
static class ParentD {
static void calculate() {
}
}
static class ChildD extends ParentD {
static void calculateExtended() { // Compliant - different name
}
}
// --- Compliant: private superclass method ---
static class ParentE {
private static void internalHelper() {
}
}
static class ChildE extends ParentE {
static void internalHelper() { // Compliant - parent method is private
}
}
// --- Compliant: interface static methods (not inherited) ---
interface Printable {
static void print() {
}
}
static class Printer implements Printable {
static void print() { // Compliant - interface static methods are not inherited
}
}
// --- Generics: hiding with generic parameter types ---
static class GenericParent<T> {
static void transform(List<String> items) {
}
}
static class GenericChild extends GenericParent<Integer> {
static void transform(List<String> items) { // Noncompliant {{Rename this method; it hides "transform" in "GenericParent".}}
}
}
// Note: static-in-child/instance-in-parent and instance-in-child/static-in-parent
// cases are not tested here because they are compilation errors in Java.
// --- Hiding through intermediate class that doesn't define the method ---
static class GrandParent {
static void legacy() {
}
}
static class IntermediateParent extends GrandParent {
// does not override legacy()
}
static class GrandChild extends IntermediateParent {
static void legacy() { // Noncompliant {{Rename this method; it hides "legacy" in "GrandParent".}}
}
}
// --- Hiding a method from a binary dependency (JDK class) ---
// Covers the branch where declaration() returns null
static class MyThread extends Thread {
public static void sleep(long millis) throws InterruptedException { // Noncompliant {{Rename this method; it hides "sleep" in "Thread".}}
}
}
// --- Compliant: parent has a field with same name as child's static method ---
static class ParentWithField {
static int action = 0;
}
static class ChildWithMethodSameNameAsField extends ParentWithField {
static void action() { // Compliant - parent has a field, not a method
}
}
// --- Compliant: parent has non-static non-private method, child has static method with different params ---
// (Same name + same params + static child + non-static parent is a compile error)
static class ParentWithInstanceMethod {
void doWork(int x) {
}
static void doWork(String s) {
}
}
static class ChildWithStaticMethod extends ParentWithInstanceMethod {
static void doWork(String s) { // Noncompliant {{Rename this method; it hides "doWork" in "ParentWithInstanceMethod".}}
}
}
// --- Multiple methods hiding from the same parent ---
static class MultiParent {
static void first() {
}
static void second() {
}
}
static class MultiChild extends MultiParent {
static void first() { // Noncompliant {{Rename this method; it hides "first" in "MultiParent".}}
}
static void second() { // Noncompliant {{Rename this method; it hides "second" in "MultiParent".}}
}
}
// --- Compliant: intentional hiding with @Deprecated annotation ---
static class DeprecatingParent {
static void oldMethod() {
}
static String convert(String input) {
return input;
}
}
static class DeprecatingChild extends DeprecatingParent {
@Deprecated
static void oldMethod() { // Compliant - intentional hiding with @Deprecated
throw new UnsupportedOperationException();
}
@Deprecated
static String convert(String input) { // Compliant - intentional hiding with @Deprecated
throw new UnsupportedOperationException();
}
}
// --- Compliant: intentional hiding with @DoNotCall annotation ---
static class DoNotCallParent {
static void unsafeMethod() {
}
}
static class DoNotCallChild extends DoNotCallParent {
@DoNotCall("Use alternative method")
static void unsafeMethod() { // Compliant - intentional hiding with @DoNotCall
throw new UnsupportedOperationException();
}
}
// --- Compliant: intentional hiding with @InlineMe annotation ---
static class InlineMeParent {
static String oldFormat(String input) {
return input;
}
}
static class InlineMeChild extends InlineMeParent {
@InlineMe(replacement = "InlineMeParent.newFormat(input)")
static String oldFormat(String input) { // Compliant - intentional hiding with @InlineMe
return input;
}
}
// --- Compliant: intentional hiding with @ApiStatus.Obsolete annotation ---
static class ObsoleteParent {
static void oldApi() {
}
}
static class ObsoleteChild extends ObsoleteParent {
@ApiStatus.Obsolete
static void oldApi() { // Compliant - intentional hiding with @ApiStatus.Obsolete
}
}
// --- Compliant: intentional hiding with @ApiStatus.ScheduledForRemoval annotation ---
static class ScheduledForRemovalParent {
static void legacyMethod() {
}
}
static class ScheduledForRemovalChild extends ScheduledForRemovalParent {
@ApiStatus.ScheduledForRemoval
static void legacyMethod() { // Compliant - intentional hiding with @ApiStatus.ScheduledForRemoval
}
}
// --- Compliant: intentional hiding with both @Deprecated and @DoNotCall ---
static class CombinedParent {
static void legacyApi() {
}
}
static class CombinedChild extends CombinedParent {
@Deprecated
@DoNotCall("Use newApi instead")
static void legacyApi() { // Compliant - intentional hiding with @Deprecated and @DoNotCall
throw new UnsupportedOperationException();
}
}
// --- Noncompliant: hiding without any deprecation annotation ---
static class PlainParent {
static void compute() {
}
}
static class PlainChild extends PlainParent {
static void compute() { // Noncompliant {{Rename this method; it hides "compute" in "PlainParent".}}
}
}
// --- Compliant: static factory returning a more specific type ---
static class ImmutableCollectionLike {
static ImmutableCollectionLike of() {
return new ImmutableCollectionLike();
}
static Collection<String> copyOf(Collection<String> elements) {
return elements;
}
static Object create() {
return new Object();
}
static Object helper() {
return new Object();
}
static Builder builder() {
return new Builder();
}
static class Builder {
}
}
static class ImmutableSetLike extends ImmutableCollectionLike {
static ImmutableSetLike of() { // Compliant - covariant static factory
return new ImmutableSetLike();
}
static List<String> copyOf(Collection<String> elements) { // Noncompliant {{Rename this method; it hides "copyOf" in "ImmutableCollectionLike".}}
return new ArrayList<>(elements);
}
static Object create() { // Noncompliant {{Rename this method; it hides "create" in "ImmutableCollectionLike".}}
return new Object();
}
static String helper() { // Noncompliant {{Rename this method; it hides "helper" in "ImmutableCollectionLike".}}
return "";
}
static Builder builder() { // Compliant - covariant static factory returning a nested type
return new Builder();
}
static class Builder extends ImmutableCollectionLike.Builder {
}
}
static class SameReturnParent {
static Integer value() {
return 1;
}
}
static class SameReturnChild extends SameReturnParent {
static Integer value() { // Noncompliant {{Rename this method; it hides "value" in "SameReturnParent".}}
return 2;
}
}
// --- Compliant: JUnit 3 suite() methods have to be redeclared in each test class ---
public static class ParentTestCase extends TestCase {
public static Test suite() {
return new TestSuite(ParentTestCase.class);
}
public static Test other() {
return new TestSuite(ParentTestCase.class);
}
}
public static class ChildTestCase extends ParentTestCase {
public static Test suite() { // Compliant - JUnit 3 suite
return new TestSuite(ChildTestCase.class);
}
public static Test other() { // Noncompliant {{Rename this method; it hides "other" in "ParentTestCase".}}
return new TestSuite(ChildTestCase.class);
}
}
public static class ParentTestSuiteCase extends TestCase {
public static TestSuite suite() {
return new TestSuite(ParentTestSuiteCase.class);
}
}
public static class ChildTestSuiteCase extends ParentTestSuiteCase {
public static TestSuite suite() { // Compliant - JUnit 3 suite
return new TestSuite(ChildTestSuiteCase.class);
}
}
}