Skip to content

Commit b988be8

Browse files
committed
ruby: improve help file
This has improved autofixes I hope it also helps humans
1 parent 85e27ca commit b988be8

File tree

3 files changed

+53
-38
lines changed

3 files changed

+53
-38
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Method call on `nil`
2+
3+
## Description
4+
In Ruby, it is not necessary to explicitly initialize variables.
5+
If a local variable has not been explicitly initialized, it will have the value `nil`. If this happens unintended, though, the variable will not represent an object with the expected methods, and a method call on the variable will raise a `NoMethodError`.
6+
7+
## Recommendation
8+
9+
Ensure that the variable cannot be `nil` at the point hightligted by the alert.
10+
This can be achieved by using a safe navigation or adding a check for `nil`.
11+
12+
Note: You do not need to explicitly initialize the variable, if you can make the program deal with the possible `nil` value. In particular, initializing the variable to `nil` will have no effect, as this is already the value of the variable. If `nil` is the only possibly default value, you need to handle the `nil` value instead of initializing the variable.
13+
14+
## Examples
15+
16+
In the following code, the call to `create_file` may fail and then the call `f.close` will raise a `NoMethodError` since `f` will be `nil` at that point.
17+
18+
```ruby
19+
def dump(x)
20+
f = create_file
21+
f.puts(x)
22+
ensure
23+
f.close
24+
end
25+
```
26+
27+
We can fix this by using safe navigation:
28+
```ruby
29+
def dump(x)
30+
f = create_file
31+
f.puts(x)
32+
ensure
33+
f&.close
34+
end
35+
```
36+
37+
## References
38+
39+
- https://www.rubyguides.com/: [Nil](https://www.rubyguides.com/2018/01/ruby-nil/)
40+
- https://ruby-doc.org/: [NoMethodError](https://ruby-doc.org/core-2.6.5/NoMethodError.html)
41+

ruby/ql/src/queries/variables/UninitializedLocal.qhelp

Lines changed: 0 additions & 37 deletions
This file was deleted.

ruby/ql/src/queries/variables/UninitializedLocal.ql

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,24 @@ private predicate isNilChecked(LocalVariableReadAccess read) {
7272
)
7373
}
7474

75+
/**
76+
* Holds if `name` is the name of a method defined on `nil`.
77+
* See https://ruby-doc.org/core-2.5.8/NilClass.html
78+
*/
79+
private predicate isNilMethodName(string name) {
80+
name in [
81+
"inspect", "instance_of?", "is_a?", "kind_of?", "method", "nil?", "rationalize", "to_a",
82+
"to_c", "to_f", "to_h", "to_i", "to_r", "to_s"
83+
]
84+
}
85+
7586
class RelevantLocalVariableReadAccess extends LocalVariableReadAccess instanceof TVariableAccessReal
7687
{
7788
RelevantLocalVariableReadAccess() {
7889
not isInBooleanContext(this) and
7990
not isNilChecked(this) and
8091
not isGuarded(this) and
81-
this = any(MethodCall m).getReceiver()
92+
this = any(MethodCall m | not isNilMethodName(m.getMethodName())).getReceiver()
8293
}
8394
}
8495

0 commit comments

Comments
 (0)