Skip to content

Commit 54506e1

Browse files
SONARKT-301 - Implement rule S6524: collection should be immutable (#390)
1 parent f8e1a28 commit 54506e1

File tree

10 files changed

+745
-0
lines changed

10 files changed

+745
-0
lines changed
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
package checks
2+
3+
class CollectionShouldBeImmutableCheckSample {
4+
fun MutableCollection<Int>.doSomething(): Unit {} // Noncompliant
5+
6+
//let also apply run with
7+
fun nonCompliant(
8+
x: MutableList<Int>, // Noncompliant {{Make this collection immutable.}}
9+
y: MutableSet<String>, // Noncompliant
10+
// ^^^^^^^^^^^^^^^^^^^^^
11+
z: MutableMap<Int, Int>, // Noncompliant
12+
a: MutableList<Int>, // compliant, FN
13+
b: MutableList<Int>, // Noncompliant
14+
c: MutableList<Int>, // compliant, FN
15+
): Unit {
16+
baz(x.toList().toMutableList())
17+
baz(doNothing(x).toMutableList())
18+
doNothing(x)
19+
x.reduce { acc, it -> acc + it }
20+
x + 1
21+
x.size
22+
for (i in x) {
23+
println(i)
24+
}
25+
x.foo()
26+
id(x + listOf(1, 2, 3))
27+
y.contains("a")
28+
y.map { it + "a" }
29+
z[1]
30+
doNothing(x, y, z)
31+
a.let { it.size }
32+
a.let { it.also { with(it, { this.size }) } }
33+
Pair(1, b.reduce { acc, i -> i + acc })
34+
id(c)
35+
}
36+
37+
fun List<Int>.toList(): List<Int> = this // compliant
38+
fun baz(list : MutableList<Int>): Unit {} // Noncompliant
39+
40+
fun List<Int>.foo(): Unit {} // Compliant
41+
fun doNothing(a : List<Int>, b : Set<String>, c : Map<Int,Int>): Unit {}
42+
fun doNothing(a : List<Int>): List<Int> { return a } // Compliant
43+
44+
fun <A>id(a : A): A = a // Compliant
45+
46+
fun compliantScopedFunctions(
47+
a: MutableList<Int>, // Compliant
48+
b: MutableList<Int>, // Compliant
49+
c: MutableList<Int>, // Compliant
50+
d: MutableList<Int>, // Compliant
51+
e: MutableList<Int>, // Compliant
52+
f: MutableList<Int>, // Compliant
53+
crazy: MutableList<Int>,
54+
): Unit { // Compliant
55+
a.let { it.add(1) }
56+
b.also { it.add(1) }
57+
c.apply { add(1) }
58+
d.run { add(1) }
59+
with(e) { add(1) }
60+
f.let { it.let { it.let { it.add(1) } } }
61+
crazy.let { it.also { it.apply { it.run { with(this) { it.add(1) } } } } }
62+
}
63+
64+
fun MutableList<Int>.doSomething2(): MutableList<Int> { return this } // Noncompliant
65+
66+
fun compliantFunctionsCalledOn(
67+
a: MutableList<Int>, // Compliant
68+
b: MutableList<Int>, // Compliant
69+
c: List<Int>, // Compliant
70+
d: MutableList<Int>, // Compliant
71+
e: MutableMap<Int, Int>, // Compliant
72+
f: MutableList<Int>, // Compliant
73+
g: MutableList<Int>, // Compliant
74+
h: MutableSet<Int>, // Compliant
75+
i: MutableList<Int>, // Compliant
76+
j: MutableList<Int>, // Compliant
77+
k: MutableList<Int>, // Compliant
78+
l: MutableList<Int>, // Compliant
79+
m: MutableList<Int>, // Compliant
80+
n: MutableList<Int>, // Compliant
81+
): Unit {
82+
a.add(1)
83+
b.iterator()
84+
c.map { it + 1}
85+
d.add(1)
86+
e.remove(1)
87+
f.doSomething()
88+
g.doSomething2()
89+
h.doSomething()
90+
((i)).doSomething()
91+
j.doSomething2().doSomething2().doSomething2()
92+
when (k) {
93+
is MutableList<Int> -> k.doSomething()
94+
}
95+
l!!.doSomething()
96+
m?.doSomething()
97+
if(true){n}else{n}.doSomething()
98+
}
99+
100+
101+
fun compliantBinaryExprCalledOn(
102+
c: List<Int>, // Compliant
103+
d: MutableList<Int>, // Compliant
104+
e: MutableList<Int>, // Compliant
105+
f: MutableList<Int>, // Compliant
106+
g: MutableList<Int>, // Compliant
107+
): Unit {
108+
c[0]
109+
d += 1
110+
e -= 1
111+
f[0] = 1
112+
(g)[0] = 1
113+
}
114+
115+
116+
117+
fun compliantCalledInFun(
118+
a: MutableList<Int>, // Compliant
119+
b: MutableList<Int>, // Compliant
120+
c: MutableList<Int>, // Compliant
121+
d: MutableList<Int>, // Compliant
122+
e: MutableList<Int>, // Compliant
123+
f: MutableList<Int> // Compliant
124+
): Unit {
125+
foo_(a)
126+
foo2(b)
127+
foo_(((c)))
128+
foo_(d!!)
129+
foo_(if(true){e}else{e})
130+
Pair(f, 1)
131+
}
132+
133+
fun foo_(x : MutableList<Int>): Unit {} // Noncompliant {{Make this collection immutable.}}
134+
fun foo2(x : MutableCollection<Int>): Unit {} // Noncompliant
135+
136+
137+
fun nonCompliantParameter(list: MutableList<Int>): Int { // Noncompliant
138+
return list.reduce { acc, it -> acc + it}
139+
}
140+
141+
fun compliantParameter(list: List<Int>): Int { // Compliant
142+
return list.reduce { acc, it -> acc + it}
143+
}
144+
145+
fun MutableList<Int>.compliantDelegate(): Int { // Compliant
146+
this.add(1)
147+
return reduce { acc, it -> acc + it }
148+
}
149+
150+
151+
fun MutableList<Int>.compliantDelegate2(): Unit { // Compliant
152+
foo_(this)
153+
}
154+
155+
fun MutableList<Int>.compliantDelegate3(): Unit { // Compliant
156+
foo_(this)
157+
add(1)
158+
}
159+
160+
fun MutableList<Int>.compliantDelegate4(): Unit { // Compliant
161+
if(add(1)) {}
162+
}
163+
164+
fun MutableList<Int>.noncompliantDelegate(): Int { // Noncompliant
165+
// ^^^^^^^^^^^^^^^^
166+
return reduce { acc, it -> acc + it}
167+
}
168+
169+
fun MutableList<Int>.noncompliantDelegate2(): Int { // compliant, FN
170+
var list = mutableListOf(1, 2, 3) // we should change noReciever to check that it is called on this
171+
list.add(1)
172+
return reduce { acc, it -> acc + it}
173+
}
174+
175+
176+
177+
class AMutableCollections : MutableCollection<Int> {
178+
override val size: Int
179+
get() = TODO()
180+
181+
override fun contains(element: Int): Boolean {
182+
TODO()
183+
}
184+
185+
override fun containsAll(elements: Collection<Int>): Boolean {
186+
TODO()
187+
}
188+
189+
override fun isEmpty(): Boolean {
190+
TODO()
191+
}
192+
193+
override fun add(element: Int): Boolean {
194+
TODO()
195+
}
196+
197+
override fun addAll(elements: Collection<Int>): Boolean {
198+
TODO()
199+
}
200+
201+
override fun clear() {
202+
TODO()
203+
}
204+
205+
override fun iterator(): MutableIterator<Int> {
206+
TODO()
207+
}
208+
209+
override fun remove(element: Int): Boolean {
210+
TODO()
211+
}
212+
213+
override fun removeAll(elements: Collection<Int>): Boolean {
214+
TODO()
215+
}
216+
217+
override fun retainAll(elements: Collection<Int>): Boolean {
218+
TODO()
219+
}
220+
}
221+
222+
fun id(x : AMutableCollections): AMutableCollections = x // compliant, for now don't know how to check that is subtype of MutableCollection
223+
224+
225+
fun foo(configure: (MutableMap<String, Any?>) -> Unit): Unit { // compliant
226+
}
227+
228+
}

0 commit comments

Comments
 (0)