rubocop-yast 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +122 -0
- data/Rakefile +24 -0
- data/lib/rubocop/cop/yast/builtins.rb +39 -30
- data/lib/rubocop/cop/yast/ops.rb +3 -157
- data/lib/rubocop/yast/builtins/builtin.rb +38 -0
- data/lib/rubocop/yast/builtins/getenv.rb +19 -0
- data/lib/rubocop/yast/builtins/time.rb +16 -0
- data/lib/rubocop/yast/builtins/y2log.rb +138 -0
- data/lib/rubocop/yast/node_helpers.rb +22 -0
- data/lib/rubocop/yast/reformatter.rb +43 -0
- data/lib/rubocop/yast/track_variable_scope.rb +184 -0
- data/lib/rubocop/yast/variable_scope.rb +2 -0
- data/lib/rubocop/yast/version.rb +1 -1
- data/rubocop-yast.gemspec +1 -0
- data/spec/builtins_spec.md +614 -0
- data/spec/builtins_spec.rb +543 -41
- data/spec/ops_spec.rb +12 -7
- data/spec/rspec_code.rb +47 -0
- data/spec/rspec_renderer.rb +206 -0
- data/spec/spec_helper.rb +21 -13
- metadata +29 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f14f2792588ff28f55867a356603deeeafe6deb
|
4
|
+
data.tar.gz: 03433493409f9d50a333391b4e05c8782a525064
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fed38028da0bd94e103e5a5091e1723857c3c5b1995216fa175f8dc6fadaefc81f77f6182abf80a6cbe7c5e7b41fda716f44150ce6a4dc3aa2a599b7cec01f6
|
7
|
+
data.tar.gz: 32e08248270ec322da28aabf4ff9fa27fc8be17729b3b64d92336106e92cf946a65d3462c4634cca7467ace025eba6ffe41b593aff467af02d09f38c16bd3d8c
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -9,3 +9,125 @@ rubocop-yast
|
|
9
9
|
[](http://inch-ci.org/github/lslezak/rubocop-yast)
|
10
10
|
|
11
11
|
|
12
|
+
This is a plugin for [RuboCop](https://github.com/bbatsov/rubocop)
|
13
|
+
a Ruby static code analyzer. It was inspired by [Rubocop-Rspec](https://github.com/nevir/rubocop-rspec)
|
14
|
+
and [YCP Zombie Killer](https://github.com/yast/zombie-killer).
|
15
|
+
|
16
|
+
The goal is to create a Rubocop plugin which can check for
|
17
|
+
[YaST](http://yast.github.io/) specific issues. Optionally it should allow to
|
18
|
+
covert some ugly code parts introduced by the automatic code conversion done by
|
19
|
+
[YCP Killer](https://github.com/yast/ycp-killer) (conversion from YCP to Ruby).
|
20
|
+
|
21
|
+
Check [the test descriptions](spec/builtins_spec.md) to see the examples of offense
|
22
|
+
detection and code conversion.
|
23
|
+
|
24
|
+
*The plugin is currently in early development, always manually check the chages
|
25
|
+
done by the plugin! It can eat your code... ;-)*
|
26
|
+
|
27
|
+
|
28
|
+
Installation
|
29
|
+
------------
|
30
|
+
|
31
|
+
The plugin is published at [rubygems.org](https://rubygems.org/gems/rubocop-yast),
|
32
|
+
you can install it using the `gem` command:
|
33
|
+
|
34
|
+
```shell
|
35
|
+
sudo gem install rubocop-yast
|
36
|
+
```
|
37
|
+
|
38
|
+
Usage
|
39
|
+
-----
|
40
|
+
|
41
|
+
You need to manually load the Yast plugin into RuboCop to run the extra checks.
|
42
|
+
There are two options:
|
43
|
+
|
44
|
+
- Use `--require rubocop-yast` command line option when invoking `rubocop`
|
45
|
+
- Enable the plugin in `.rubocop.yml` file:
|
46
|
+
```yaml
|
47
|
+
require:
|
48
|
+
- rubocop-yast
|
49
|
+
```
|
50
|
+
|
51
|
+
See the [RuboCop documentation](https://github.com/bbatsov/rubocop#loading-extensions).
|
52
|
+
|
53
|
+
Configuration
|
54
|
+
-------------
|
55
|
+
|
56
|
+
You can configure Rubocop-Yast the same way as the standard RuboCop checks
|
57
|
+
(see the [RuboCop configuration](https://github.com/bbatsov/rubocop#configuration)):
|
58
|
+
|
59
|
+
```yaml
|
60
|
+
# Check for obsolete Builtins.* calls
|
61
|
+
Yast/Builtins:
|
62
|
+
Enabled: true
|
63
|
+
|
64
|
+
# Check for obsolete Ops.* calls
|
65
|
+
Yast/Ops:
|
66
|
+
Enabled: true
|
67
|
+
# in the safe mode only safe places are reported and fixed
|
68
|
+
SafeMode: true
|
69
|
+
```
|
70
|
+
|
71
|
+
Development
|
72
|
+
-----------
|
73
|
+
|
74
|
+
### Prerequisites
|
75
|
+
|
76
|
+
For development you need some extra development gems. The best way is to install them with [Bundler](http://bundler.io/). To avoid a possible collision with system gems it is recommended
|
77
|
+
to install the gems into a local subdirectory using
|
78
|
+
|
79
|
+
```shell
|
80
|
+
bundle install --path vendor/bundle
|
81
|
+
```
|
82
|
+
|
83
|
+
### Source Directories
|
84
|
+
|
85
|
+
* [`config/default.yml`](config/default.yml) contains the default Cop configurations
|
86
|
+
* [`lib/rubocop/cop/yast`](lib/rubocop/yast) contains Yast Cops (the checks which are called
|
87
|
+
from the main rubocop script)
|
88
|
+
* [`lib/rubocop/yast`](lib/rubocop/yast) contains libraries used by the Cops
|
89
|
+
* [`spec`](spec) contains tests, some tests are automatically generated from a MarkDown
|
90
|
+
documentation
|
91
|
+
|
92
|
+
### Running Tests
|
93
|
+
|
94
|
+
```
|
95
|
+
bundle exec rake
|
96
|
+
```
|
97
|
+
|
98
|
+
By default the tests check the code coverage, if it is below 95% the test fails although
|
99
|
+
there was no test failure.
|
100
|
+
|
101
|
+
### Autocorrecting Rubocop Issues
|
102
|
+
|
103
|
+
```
|
104
|
+
bundle exec rake rubocop:auto_correct
|
105
|
+
```
|
106
|
+
|
107
|
+
You can also load the plugin itself to verify that plugin loading works correctly.
|
108
|
+
(Plugin loading is not covered by tests as it needs the base Rubocop framework.)
|
109
|
+
|
110
|
+
```
|
111
|
+
bundle exec rubocop -r rubocop-yast
|
112
|
+
```
|
113
|
+
|
114
|
+
### Building a Gem
|
115
|
+
|
116
|
+
```
|
117
|
+
bundle exec rake build
|
118
|
+
```
|
119
|
+
|
120
|
+
This builds `pkg/rubocop-yast-<version>.gem` gem file, it can be installed locally using
|
121
|
+
```
|
122
|
+
sudo gem install --local pkg/rubocop-yast-<version>.gem
|
123
|
+
```
|
124
|
+
|
125
|
+
### Publishing the Gem to Rubygems.org
|
126
|
+
|
127
|
+
Increase the version in [`lib/rubocop/yast/version.rb`](lib/rubocop/yast/version.rb) file
|
128
|
+
and then run:
|
129
|
+
|
130
|
+
```
|
131
|
+
bundle exec rake release
|
132
|
+
```
|
133
|
+
|
data/Rakefile
CHANGED
@@ -10,8 +10,32 @@ rescue Bundler::BundlerError => e
|
|
10
10
|
exit e.status_code
|
11
11
|
end
|
12
12
|
|
13
|
+
require "redcarpet"
|
14
|
+
require_relative "spec/rspec_renderer"
|
15
|
+
|
16
|
+
def render_markdown(renderer_class, task)
|
17
|
+
puts "Rendering file: #{task.name}"
|
18
|
+
markdown = Redcarpet::Markdown.new(renderer_class, fenced_code_blocks: true)
|
19
|
+
|
20
|
+
string = markdown.render(File.read(task.prerequisites[0]))
|
21
|
+
File.write(task.name, string)
|
22
|
+
end
|
23
|
+
|
24
|
+
renderer = "spec/rspec_renderer.rb"
|
25
|
+
|
26
|
+
file "spec/builtins_spec.rb" => ["spec/builtins_spec.md", renderer] do |t|
|
27
|
+
render_markdown(RSpecRenderer, t)
|
28
|
+
end
|
29
|
+
|
30
|
+
file "spec/builtins_spec.html" => ["spec/builtins_spec.md", renderer] do |t|
|
31
|
+
render_markdown(Redcarpet::Render::HTML, t)
|
32
|
+
end
|
33
|
+
desc "Render the specification to HTML locally"
|
34
|
+
task html: ["spec/builtins_spec.html"]
|
35
|
+
|
13
36
|
require "rspec/core/rake_task"
|
14
37
|
RSpec::Core::RakeTask.new(:spec)
|
38
|
+
task spec: ["spec/builtins_spec.rb"]
|
15
39
|
|
16
40
|
require "rubocop/rake_task"
|
17
41
|
RuboCop::RakeTask.new(:rubocop)
|
@@ -1,5 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require "rubocop/yast/builtins/builtin"
|
4
|
+
require "rubocop/yast/builtins/getenv"
|
5
|
+
require "rubocop/yast/builtins/time"
|
6
|
+
require "rubocop/yast/builtins/y2log"
|
7
|
+
|
3
8
|
module RuboCop
|
4
9
|
module Cop
|
5
10
|
module Yast
|
@@ -7,23 +12,9 @@ module RuboCop
|
|
7
12
|
class Builtins < Cop
|
8
13
|
include AST::Sexp
|
9
14
|
|
10
|
-
|
15
|
+
attr_reader :handlers, :default_handler
|
11
16
|
|
12
|
-
|
13
|
-
ALLOWED_FUNCTIONS = [
|
14
|
-
# locale dependent sorting in not available in Ruby stdlib
|
15
|
-
:lsort,
|
16
|
-
# gettext helpers
|
17
|
-
:dgettext,
|
18
|
-
:dngettext,
|
19
|
-
:dpgettext,
|
20
|
-
# crypt* helpers
|
21
|
-
:crypt,
|
22
|
-
:cryptmd5,
|
23
|
-
:cryptblowfish,
|
24
|
-
:cryptsha256,
|
25
|
-
:cryptsha512
|
26
|
-
]
|
17
|
+
MSG = "Builtin call `%s` is obsolete, use native Ruby function instead."
|
27
18
|
|
28
19
|
BUILTINS_NODES = [
|
29
20
|
# Builtins.*
|
@@ -34,34 +25,52 @@ module RuboCop
|
|
34
25
|
s(:const, s(:const, s(:cbase), :Yast), :Builtins)
|
35
26
|
]
|
36
27
|
|
28
|
+
def initialize(config = nil, options = nil)
|
29
|
+
super(config, options)
|
30
|
+
|
31
|
+
@handlers = builtin_mapping
|
32
|
+
@default_handler = RuboCop::Yast::Builtins::Builtin.new
|
33
|
+
end
|
34
|
+
|
37
35
|
def on_send(node)
|
38
36
|
receiver, method_name, *_args = *node
|
39
37
|
|
38
|
+
# not an Yast builtin call or not an offense
|
40
39
|
return if !BUILTINS_NODES.include?(receiver) ||
|
41
|
-
|
40
|
+
!builtin_handler(method_name).offense?(node)
|
42
41
|
|
43
42
|
add_offense(node, :selector, format(MSG, method_name))
|
44
43
|
end
|
45
44
|
|
46
45
|
def autocorrect(node)
|
47
|
-
|
48
|
-
_builtins, message, args = *node
|
49
|
-
|
50
|
-
new_code = builtins_replacement(message, args)
|
46
|
+
_builtins, method_name, *_args = *node
|
51
47
|
|
52
|
-
|
53
|
-
end
|
48
|
+
@corrections << builtin_handler(method_name).correction(node)
|
54
49
|
end
|
55
50
|
|
56
51
|
private
|
57
52
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
53
|
+
# rubocop:disable Metrics/MethodLength
|
54
|
+
def builtin_mapping
|
55
|
+
# use the same instance for all logging functions
|
56
|
+
logging = RuboCop::Yast::Builtins::Y2log.new
|
57
|
+
|
58
|
+
{
|
59
|
+
y2debug: logging,
|
60
|
+
y2milestone: logging,
|
61
|
+
y2warning: logging,
|
62
|
+
y2error: logging,
|
63
|
+
y2security: logging,
|
64
|
+
y2internal: logging,
|
65
|
+
|
66
|
+
getenv: RuboCop::Yast::Builtins::Getenv.new,
|
67
|
+
time: RuboCop::Yast::Builtins::Time.new
|
68
|
+
}
|
69
|
+
end
|
70
|
+
# rubocop:enable Metrics/MethodLength
|
71
|
+
|
72
|
+
def builtin_handler(method)
|
73
|
+
handlers[method] || default_handler
|
65
74
|
end
|
66
75
|
end
|
67
76
|
end
|
data/lib/rubocop/cop/yast/ops.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require "rubocop/yast/
|
4
|
-
require "rubocop/yast/variable_scope"
|
3
|
+
require "rubocop/yast/track_variable_scope"
|
5
4
|
|
6
5
|
# We have encountered code that does satisfy our simplifying assumptions,
|
7
6
|
# translating it would not be correct.
|
@@ -14,7 +13,7 @@ module RuboCop
|
|
14
13
|
# This cop checks for Ops.* calls, it can autocorrect safe places or
|
15
14
|
# all places in unsafe mode
|
16
15
|
class Ops < Cop
|
17
|
-
include
|
16
|
+
include RuboCop::Yast::TrackVariableScope
|
18
17
|
|
19
18
|
# Ops replacement mapping
|
20
19
|
REPLACEMENT = {
|
@@ -26,96 +25,10 @@ module RuboCop
|
|
26
25
|
def initialize(config = nil, options = nil)
|
27
26
|
super(config, options)
|
28
27
|
|
29
|
-
@scopes = VariableScopeStack.new
|
30
28
|
@safe_mode = cop_config["SafeMode"]
|
31
29
|
@replaced_nodes = []
|
32
30
|
end
|
33
31
|
|
34
|
-
# FIXME
|
35
|
-
def process(node)
|
36
|
-
return if node.nil?
|
37
|
-
# if ! @unsafe
|
38
|
-
# oops(node, RuntimeError.new("Unknown node type #{node.type}")) \
|
39
|
-
# unless HANDLED_NODE_TYPES.include? node.type
|
40
|
-
# end
|
41
|
-
end
|
42
|
-
|
43
|
-
# currently visible scope
|
44
|
-
def scope
|
45
|
-
scopes.innermost
|
46
|
-
end
|
47
|
-
|
48
|
-
def with_new_scope_rescuing_oops(node, &block)
|
49
|
-
scopes.with_new do
|
50
|
-
block.call if block_given?
|
51
|
-
end
|
52
|
-
rescue => e
|
53
|
-
oops(node, e)
|
54
|
-
end
|
55
|
-
|
56
|
-
def on_def(node)
|
57
|
-
with_new_scope_rescuing_oops(node)
|
58
|
-
end
|
59
|
-
|
60
|
-
def on_defs(node)
|
61
|
-
with_new_scope_rescuing_oops(node)
|
62
|
-
end
|
63
|
-
|
64
|
-
def on_module(node)
|
65
|
-
with_new_scope_rescuing_oops(node)
|
66
|
-
end
|
67
|
-
|
68
|
-
def on_class(node)
|
69
|
-
with_new_scope_rescuing_oops(node)
|
70
|
-
end
|
71
|
-
|
72
|
-
def on_sclass(node)
|
73
|
-
with_new_scope_rescuing_oops(node)
|
74
|
-
end
|
75
|
-
|
76
|
-
# def on_unless
|
77
|
-
# Does not exist.
|
78
|
-
# `unless` is parsed as an `if` with then_body and else_body swapped.
|
79
|
-
# Compare with `while` and `until` which cannot do that and thus need
|
80
|
-
# distinct node types.
|
81
|
-
# end
|
82
|
-
|
83
|
-
def on_case(node)
|
84
|
-
expr, *cases = *node
|
85
|
-
process(expr)
|
86
|
-
|
87
|
-
cases.each do |case_|
|
88
|
-
scopes.with_copy do
|
89
|
-
process(case_)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# clean slate
|
94
|
-
scope.clear
|
95
|
-
end
|
96
|
-
|
97
|
-
def on_lvasgn(node)
|
98
|
-
name, value = * node
|
99
|
-
return if value.nil? # and-asgn, or-asgn, resbody do this
|
100
|
-
scope[name].nice = nice(value)
|
101
|
-
end
|
102
|
-
|
103
|
-
def on_and_asgn(node)
|
104
|
-
var, value = * node
|
105
|
-
return if var.type != :lvasgn
|
106
|
-
name = var.children[0]
|
107
|
-
|
108
|
-
scope[name].nice &&= nice(value)
|
109
|
-
end
|
110
|
-
|
111
|
-
def on_or_asgn(node)
|
112
|
-
var, value = * node
|
113
|
-
return if var.type != :lvasgn
|
114
|
-
name = var.children[0]
|
115
|
-
|
116
|
-
scope[name].nice ||= nice(value)
|
117
|
-
end
|
118
|
-
|
119
32
|
def on_send(node)
|
120
33
|
return unless call?(node, :Ops, :add)
|
121
34
|
|
@@ -125,75 +38,8 @@ module RuboCop
|
|
125
38
|
add_offense(node, :selector, format(MSG, method))
|
126
39
|
end
|
127
40
|
|
128
|
-
def on_block(_node)
|
129
|
-
# ignore body, clean slate
|
130
|
-
scope.clear
|
131
|
-
end
|
132
|
-
alias_method :on_for, :on_block
|
133
|
-
|
134
|
-
def on_while(_node)
|
135
|
-
# ignore both condition and body,
|
136
|
-
# with a simplistic scope we cannot handle them
|
137
|
-
|
138
|
-
# clean slate
|
139
|
-
scope.clear
|
140
|
-
end
|
141
|
-
alias_method :on_until, :on_while
|
142
|
-
|
143
|
-
# Exceptions:
|
144
|
-
# `raise` is an ordinary :send for the parser
|
145
|
-
|
146
|
-
def on_rescue(node)
|
147
|
-
# (:rescue, begin-block, resbody..., else-block-or-nil)
|
148
|
-
_begin_body, *_rescue_bodies, _else_body = *node
|
149
|
-
|
150
|
-
# FIXME
|
151
|
-
# @source_rewriter.transaction do
|
152
|
-
# process(begin_body)
|
153
|
-
# process(else_body)
|
154
|
-
# rescue_bodies.each do |r|
|
155
|
-
# process(r)
|
156
|
-
# end
|
157
|
-
# end
|
158
|
-
# rescue TooComplexToTranslateError
|
159
|
-
# warning "begin-rescue is too complex to translate due to a retry"
|
160
|
-
# end
|
161
|
-
end
|
162
|
-
|
163
|
-
def on_resbody(_node)
|
164
|
-
# How it is parsed:
|
165
|
-
# (:resbody, exception-types-or-nil, exception-variable-or-nil, body)
|
166
|
-
# exception-types is an :array
|
167
|
-
# exception-variable is a (:lvasgn, name), without a value
|
168
|
-
|
169
|
-
# A rescue means that *some* previous code was skipped.
|
170
|
-
# We know nothing. We could process the resbodies individually,
|
171
|
-
# and join begin-block with else-block, but it is little worth
|
172
|
-
# because they will contain few zombies.
|
173
|
-
scope.clear
|
174
|
-
end
|
175
|
-
|
176
|
-
def on_ensure(_node)
|
177
|
-
# (:ensure, guarded-code, ensuring-code)
|
178
|
-
# guarded-code may be a :rescue or not
|
179
|
-
|
180
|
-
scope.clear
|
181
|
-
end
|
182
|
-
|
183
|
-
def on_retry(_node)
|
184
|
-
# that makes the :rescue a loop, top-down data-flow fails
|
185
|
-
# FIXME
|
186
|
-
# raise TooComplexToTranslateError
|
187
|
-
end
|
188
|
-
|
189
41
|
private
|
190
42
|
|
191
|
-
def oops(node, exception)
|
192
|
-
puts "Node exception @ #{node.loc.expression}"
|
193
|
-
puts "Offending node: #{node.inspect}"
|
194
|
-
raise exception unless exception.is_a?(TooComplexToTranslateError)
|
195
|
-
end
|
196
|
-
|
197
43
|
def call?(node, namespace, message)
|
198
44
|
n_receiver, n_message = *node
|
199
45
|
n_receiver && n_receiver.type == :const &&
|
@@ -219,7 +65,7 @@ module RuboCop
|
|
219
65
|
"#{arg2.loc.expression.source}"
|
220
66
|
end
|
221
67
|
|
222
|
-
attr_reader :
|
68
|
+
attr_reader :safe_mode
|
223
69
|
end
|
224
70
|
end
|
225
71
|
end
|