Repository navigation
Expand file tree
/
Copy pathTernaryOperatorSameOperationCheckSample.java
More file actions
242 lines (187 loc) · 9.68 KB
/
Copy pathTernaryOperatorSameOperationCheckSample.java
File metadata and controls
242 lines (187 loc) · 9.68 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
package checks;
import java.util.function.Function;
class TernaryOperatorSameOperationCheckSample {
boolean condition;
boolean other;
TernaryOperatorSameOperationCheckSample obj;
TernaryOperatorSameOperationCheckSample obj2;
void testMethodInvocations() {
String a = "a";
String b = "b";
String x = "x";
String y = "y";
String z = "z";
// Method invocations - Noncompliant
String m1 = condition ? foo(a) : foo(b); // Noncompliant {{Move the conditional expression inside this operation.}}
String m2 = condition ? this.foo(a) : this.foo(b); // Noncompliant
String m3 = condition ? obj.foo(a) : obj.foo(b); // Noncompliant
String m4 = condition ? StaticClass.foo(a) : StaticClass.foo(b); // Noncompliant
// Method invocations with multiple args where some differ - Noncompliant
String m5 = condition ? foo(a, x) : foo(b, x); // Noncompliant
// Method invocations with multiple args where all differ - Compliant
String m6 = condition ? foo(a, x) : foo(b, y); // Compliant - more than one argument differs
// Method invocations - Compliant (different operations or same arguments)
String c1 = condition ? foo(a) : bar(b); // Compliant - different methods
String c2 = condition ? foo(a) : foo(a); // Compliant - same arguments
String c3 = condition ? foo(a) : foo(a, b); // Compliant - different number of arguments
}
void testMethodInvocationsEdgeCases() {
String a = "a";
String b = "b";
// No-arg methods - Compliant (no arguments to differ)
String e1 = condition ? noArg() : noArg(); // Compliant
// Different receivers - Compliant
String e2 = condition ? obj.foo(a) : obj2.foo(b); // Compliant - different receiver objects
// Different kinds in true/false - Compliant
Object e3 = condition ? foo(a) : new Foo(b); // Compliant - method vs constructor
Object e4 = condition ? a : b; // Compliant - simple identifiers, not method/new/array
// String literal - Compliant
String e5 = condition ? "hello" : "world"; // Compliant
// Numeric literal - Compliant
int e6 = condition ? 1 : 2; // Compliant
}
void testNewClass() {
String a = "a";
String b = "b";
// New class - Noncompliant
Object n1 = condition ? new Foo(a) : new Foo(b); // Noncompliant {{Move the conditional expression inside this operation.}}
// New class with multiple args where some differ - Noncompliant
Object n2 = condition ? new Foo(a, b) : new Foo(b, b); // Noncompliant
// New class with multiple args where all differ - Compliant
Object n3 = condition ? new Foo(a, a) : new Foo(b, b); // Compliant - more than one argument differs
// New class - Compliant
Object c4 = condition ? new Foo(a) : new Bar(b); // Compliant - different classes
Object c5 = condition ? new Foo(a) : new Foo(a); // Compliant - same arguments
Object c6 = condition ? new Foo(a) : new Foo(a, b); // Compliant - different arguments count
}
void testArrayAccess() {
String[] arr = new String[10];
String[] otherArr = new String[10];
int i = 0;
int j = 1;
// Array access - Noncompliant
String a1 = condition ? arr[i] : arr[j]; // Noncompliant {{Move the conditional expression inside this operation.}}
// Array access - Compliant
String c7 = condition ? arr[i] : arr[i]; // Compliant - same index
String c8 = condition ? arr[i] : otherArr[j]; // Compliant - different arrays
}
void testNestedTernary() {
String x = "x";
String y = "y";
String z = "z";
// Nested ternary - Noncompliant (outer ternary has same operation after parentheses skip)
String n3 = condition ? (other ? foo(x) : foo(y)) : foo(z); // Noncompliant {{Move the conditional expression inside this operation.}}
// Nested ternary - Compliant (inner ternary is not same operation)
String c9 = condition ? (other ? foo(x) : bar(x)) : foo(z); // Compliant
}
void testMemberSelectEdgeCases() {
String a = "a";
String b = "b";
// Same receiver, different method names - Compliant
String ms1 = condition ? obj.foo(a) : obj.bar(b); // Compliant - different method names
// Method invocation vs member select method invocation - Compliant
String ms2 = condition ? foo(a) : obj.foo(b); // Compliant - identifier vs member select
}
void testOther() {
String a = "a";
String b = "b";
// Method reference - Compliant
Function<String, String> f1 = condition ? this::foo : this::method; // Compliant
// Multiple different operations - Compliant
String c10 = condition ? foo(a) : bar(b); // Compliant
Object c11 = condition ? new Foo(a) : new Bar(b); // Compliant
// Array access vs method invocation - Compliant
String[] arr = {a, b};
Object o1 = condition ? arr[0] : foo(b); // Compliant - different expression kinds
// New class vs array access - Compliant
Object o2 = condition ? new Foo(a) : arr[0]; // Compliant - different expression kinds
}
void testOverloadedMethods() {
// Overloaded methods with different parameter types - Compliant (different method symbols)
Object ov1 = condition ? overloaded(1) : overloaded("x"); // Compliant - different overloads
Object ov2 = condition ? this.overloaded(1) : this.overloaded("x"); // Compliant - different overloads
// Same overload, different arguments - Noncompliant
Object ov3 = condition ? overloaded(1) : overloaded(2); // Noncompliant
Object ov4 = condition ? overloaded("a") : overloaded("b"); // Noncompliant
}
void testOverloadedConstructors() {
// Overloaded constructors with different parameter types - Compliant (different constructor symbols)
Object oc1 = condition ? new OverloadedCtor(1) : new OverloadedCtor("x"); // Compliant - different constructors
}
void testNewClassWithClassBody() {
String a = "a";
String b = "b";
// Anonymous class body - Compliant (class bodies make each instantiation unique)
Object ac1 = condition ? new Foo(a) { } : new Foo(b) { }; // Compliant - anonymous class bodies
Object ac2 = condition ? new Foo(a) { } : new Foo(b); // Compliant - one has class body
}
void testQualifiedInstantiations() {
String a = "a";
String b = "b";
// Qualified instantiation with same enclosing expression - Noncompliant
Object qi1 = condition ? obj.new Inner(a) : obj.new Inner(b); // Noncompliant
// Qualified instantiation with different enclosing expression - Compliant
Object qi2 = condition ? obj.new Inner(a) : obj2.new Inner(b); // Compliant - different enclosing expressions
// Mixed: unqualified vs qualified - Compliant
Object qi3 = condition ? new Inner(a) : obj.new Inner(b); // Compliant - one has enclosing, other doesn't
}
void testNonIdentifierReceiver() {
String a = "a";
String b = "b";
// Non-identifier receiver (method call as receiver) - Noncompliant
Object nir1 = condition ? getObj().foo(a) : getObj().foo(b); // Noncompliant
}
void testComplexArguments(String value, StringBuilder buffer, int index) {
String c12 = condition ? foo(value.substring(1)) : foo(value); // Compliant - method invocation as differing argument
String c13 = condition ? foo(value.substring(1)) : foo(value.substring(2)); // Compliant - nested invocations
Object c14 = condition ? new Thread(() -> {}) : new Thread(this::run); // Compliant - lambda and method reference
Object c15 = condition ? new Foo((String) obj.toString()) : new Foo(value); // Compliant - cast
Object c16 = condition ? new Foo(value + "x") : new Foo(value); // Compliant - binary expression
String c17 = condition ? foo(new String("a")) : foo(value); // Compliant - object creation
String[] arr = {value};
String c18 = condition ? arr[index + 1] : arr[index]; // Compliant - complex index
String s1 = condition ? foo("abc") : foo("def"); // Noncompliant
String s2 = condition ? foo(this.field) : foo(value); // Noncompliant
String s3 = condition ? foo(obj.field) : foo(obj2.field); // Noncompliant
String s4 = condition ? foo((value)) : foo(field); // Noncompliant
Object s5 = condition ? overloaded(-1) : overloaded(index); // Noncompliant
String s6 = condition ? arr[0] : arr[index]; // Noncompliant
}
void testDifferentArgumentTypes(int primitive, Integer boxed, long longValue, Object object, String string) {
Object t1 = condition ? takesLong(primitive) : takesLong(longValue); // Compliant - different argument types
Object t2 = condition ? takesObject(boxed) : takesObject(primitive); // Compliant - unboxing would occur
Object t3 = condition ? takesObject(string) : takesObject(object); // Compliant - different argument types
Object t4 = condition ? foo(string) : foo(null); // Compliant - null literal
Object t5 = condition ? takesLong(longValue) : takesLong(1L); // Noncompliant
}
// Private methods used in ternary
String field;
private void run() { }
private Object takesLong(long l) { return l; }
private Object takesObject(Object o) { return o; }
private String foo(String s) { return s; }
private String foo(String s, String t) { return s + t; }
private String bar(String s) { return s; }
private String method(String s) { return s; }
private String noArg() { return ""; }
private Object overloaded(int i) { return i; }
private Object overloaded(String s) { return s; }
private TernaryOperatorSameOperationCheckSample getObj() { return this; }
private static class StaticClass {
static String foo(String s) { return s; }
}
private static class Foo {
Foo(String s) {}
Foo(String s, String t) {}
}
private static class Bar {
Bar(String s) {}
}
private static class OverloadedCtor {
OverloadedCtor(int i) {}
OverloadedCtor(String s) {}
}
class Inner {
Inner(String s) {}
}
}