/
exponential_notation.rb
119 lines (109 loc) · 3.04 KB
/
exponential_notation.rb
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
# frozen_string_literal: true
module RuboCop
module Cop
module Style
# This cop enforces consistency when using exponential notation
# for numbers in the code (eg 1.2e4). Different styles are supported:
# - `scientific` which enforces a mantissa between 1 (inclusive)
# and 10 (exclusive).
# - `engineering` which enforces the exponent to be a multiple of 3
# and the mantissa to be between 0.1 (inclusive)
# and 10 (exclusive).
# - `integral` which enforces the mantissa to always be a whole number
# without trailing zeroes.
#
# @example EnforcedStyle: scientific (default)
# # Enforces a mantissa between 1 (inclusive) and 10 (exclusive).
#
# # bad
# 10e6
# 0.3e4
# 11.7e5
# 3.14e0
#
# # good
# 1e7
# 3e3
# 1.17e6
# 3.14
#
# @example EnforcedStyle: engineering
# # Enforces using multiple of 3 exponents,
# # mantissa should be between 0.1 (inclusive) and 1000 (exclusive)
#
# # bad
# 3.2e7
# 0.1e5
# 12e5
# 1232e6
#
# # good
# 32e6
# 10e3
# 1.2e6
# 1.232e9
#
# @example EnforcedStyle: integral
# # Enforces the mantissa to have no decimal part and no
# # trailing zeroes.
#
# # bad
# 3.2e7
# 0.1e5
# 120e4
#
# # good
# 32e6
# 1e4
# 12e5
#
class ExponentialNotation < Cop
include ConfigurableEnforcedStyle
def on_float(node)
add_offense(node) if offense?(node)
end
private
def scientific?(node)
mantissa, = node.source.split('e')
mantissa =~ /^-?[1-9](\.\d*[0-9])?$/
end
def engineering?(node)
mantissa, exponent = node.source.split('e')
return false unless exponent =~ /^-?\d+$/
return false unless (exponent.to_i % 3).zero?
return false if mantissa =~ /^-?\d{4}/
return false if mantissa =~ /^-?0\d/
return false if mantissa =~ /^-?0.0/
true
end
def integral(node)
mantissa, = node.source.split('e')
mantissa =~ /^-?[1-9](\d*[1-9])?$/
end
def offense?(node)
return false unless node.source['e']
case style
when :scientific
!scientific?(node)
when :engineering
!engineering?(node)
when :integral
!integral(node)
else
false
end
end
def message(_node)
case style
when :scientific
'Use a mantissa in [1, 10[.'
when :engineering
'Use an exponent divisible by 3 and a mantissa in [0.1, 1000[.'
when :integral
'Use an integer as mantissa, without trailing zero.'
end
end
end
end
end
end