skeptic 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rvmrc +1 -1
- data/CHANGELOG.md +24 -0
- data/Gemfile +1 -1
- data/README.markdown +15 -3
- data/VERSION +1 -1
- data/bin/skeptic +55 -16
- data/lib/skeptic/rules/max_method_arity.rb +83 -0
- data/lib/skeptic/rules/max_nesting_depth.rb +1 -1
- data/lib/skeptic/rules/spaces_around_operators.rb +2 -2
- data/lib/skeptic/rules.rb +1 -0
- data/lib/skeptic/sexp_visitor.rb +2 -0
- data/lib/skeptic.rb +1 -0
- data/skeptic.gemspec +9 -8
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b186a1164cdf3aec83412da18189eea9b5f009af
|
4
|
+
data.tar.gz: 3a9179e3fcca3ecbecf2ebc0614e2d81819d82c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bbc4449f25c944c6071b4f59f6c73d741b36159e08ab05c6300973d9f33a2da381cc471bc09a4908cf576516b452a1e49efc4c7d792b6c3fc1bb0c55dada27e
|
7
|
+
data.tar.gz: 67df5abdf016869af57e345edf652237854ef5f6512ac78ee5bce6805a3850b2a4563c70115e337e1a7edda532f1eccde4a91fa819d43567b34fa9e24934f953
|
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm --create 1.
|
1
|
+
rvm --create 2.1.2@skeptic
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
## 0.0.8 (2014-10-12)
|
2
|
+
|
3
|
+
Features:
|
4
|
+
- Add a rule for max method arity (thanks to [milanov](https://github.com/milanov))
|
5
|
+
- Add support for checking recursively whole directories
|
6
|
+
|
7
|
+
Bugfixes:
|
8
|
+
- Fix detection of unary operators
|
9
|
+
- Add installation instructions in the readme (thanks to [mitio](https://github.com/mitio))
|
10
|
+
- Fix handling of case statements without a testable in max nesting depth rule
|
11
|
+
|
12
|
+
## 0.0.7 (2013-12-15)
|
13
|
+
|
14
|
+
Bugfixes:
|
15
|
+
- Fix crashing in naming conventions rule
|
16
|
+
- Stop detecting unary - in space around operators rule
|
17
|
+
- Improve space around operators detection using ast context info
|
18
|
+
|
19
|
+
## 0.0.6 (2013-12-14)
|
20
|
+
|
21
|
+
Bugfixes:
|
22
|
+
- Refine bad naming detection
|
23
|
+
|
24
|
+
|
1
25
|
## 0.0.5 (2013-11-15)
|
2
26
|
|
3
27
|
Features:
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -2,9 +2,21 @@
|
|
2
2
|
|
3
3
|
_Skeptic_ is a *very* experimental static code analyzer for Ruby 1.9. It points out annoying things in your Ruby code.
|
4
4
|
|
5
|
-
I am using it for a [Ruby course in the University of Sofia](http://fmi.ruby.bg/). All the assignments the students hand it should adhere to specific style, that is automatically checked with Skeptic. Assignments that fail to meet the
|
5
|
+
I am using it for a [Ruby course in the University of Sofia](http://fmi.ruby.bg/). All the assignments the students hand it should adhere to specific style, that is automatically checked with Skeptic. Assignments that fail to meet the criteria are rejected outright. The main assumption is the "theory" of constraints - when one operates under constraints, one is more creative and ends up learning more.
|
6
6
|
|
7
|
-
You should probably not use it for
|
7
|
+
You should probably not use it for anything.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Skeptic can be installed as a Ruby gem, either via `gem install skeptic`, or better yet via Bundler.
|
12
|
+
|
13
|
+
Make sure that you have the `aspell` package installed in your system, along with its shared libraries (`libaspell`). If you're on OS X, you can use [Homebrew](http://brew.sh/) to do that:
|
14
|
+
|
15
|
+
brew install aspell
|
16
|
+
|
17
|
+
On other Linux/Unix distributions, you are free to use a package manager or another installation method of choice.
|
18
|
+
|
19
|
+
For Windows systems, check out [GNU Aspell for Win32](http://aspell.net/win32/). Install Aspell using the "Full Installer" linked in that page, then locate `aspell-15.dll` in the installation and copy it somewhere in your `PATH` as `aspell.dll`.
|
8
20
|
|
9
21
|
## Rules
|
10
22
|
|
@@ -13,7 +25,7 @@ Skeptic checks if the code complies to a number of rules and reports the violati
|
|
13
25
|
* **Valid syntax** - skeptic can check if your syntax is valid.
|
14
26
|
* **Line length** - line length does not exceed a certain number.
|
15
27
|
* **Lines per method** - methods are at most N lines long. Ignores empty lines and lines with `end`
|
16
|
-
* **Max nesting depth** - at most N levels of nesting.
|
28
|
+
* **Max nesting depth** - at most N levels of nesting. Blocks, conditions and loops are considered a level of nesting.
|
17
29
|
* **No semicolons** - stops you from using semicolons as expression delimiters.
|
18
30
|
* **No trailing whitespace** - points out if your lines end on whitespace.
|
19
31
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.8
|
data/bin/skeptic
CHANGED
@@ -7,36 +7,60 @@ parser = Trollop::Parser.new do
|
|
7
7
|
banner <<BANNER
|
8
8
|
Points out annoying things in your Ruby code. Just run with:
|
9
9
|
|
10
|
-
skeptic [options] <
|
10
|
+
skeptic [options] <path>
|
11
11
|
|
12
|
-
where
|
12
|
+
where
|
13
|
+
<path> is a path to a file or a directory\
|
14
|
+
(which would be checked recursively) and
|
15
|
+
[options] are:
|
13
16
|
BANNER
|
14
17
|
Skeptic::Rules.table.each_rule do |klass, slug, option_type, description|
|
15
18
|
opt slug, description, type: option_type
|
16
19
|
end
|
17
|
-
opt :
|
20
|
+
opt :path, 'Path to file/directory to analyze', type: :string
|
18
21
|
end
|
19
22
|
|
20
23
|
opts = Trollop::with_standard_exception_handling parser do
|
21
24
|
parsed = parser.parse ARGV
|
22
|
-
parsed[:
|
23
|
-
raise Trollop::HelpNeeded unless parsed[:
|
25
|
+
parsed[:path] ||= ARGV.shift unless parsed[:path_given]
|
26
|
+
raise Trollop::HelpNeeded unless parsed[:path]
|
24
27
|
raise Trollop::CommandlineError, "excessive arguments: #{ARGV.join(' ')}" unless ARGV.empty?
|
25
|
-
raise Trollop::CommandlineError, "
|
28
|
+
raise Trollop::CommandlineError, "resource does not exist: #{parsed[:path]}" unless File.exist? parsed[:path]
|
26
29
|
parsed
|
27
30
|
end
|
28
31
|
|
29
|
-
|
30
|
-
critic = Skeptic::Critic.new opts.select { |key, value| Skeptic::Rules.table.slugs.include? key }
|
31
|
-
critic.criticize code
|
32
|
+
CRITIC_OPTS = opts.select { |key, value| Skeptic::Rules.table.slugs.include? key }
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
def criticize_file(path)
|
35
|
+
code = File.read path
|
36
|
+
critic = Skeptic::Critic.new CRITIC_OPTS
|
37
|
+
critic.criticize code
|
38
|
+
critic.criticism
|
39
|
+
end
|
38
40
|
|
39
|
-
|
41
|
+
def criticize_directory(path)
|
42
|
+
Dir["#{path}/**/*.rb"].map do |file|
|
43
|
+
[file, criticize_file(file)]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def display_directory_criticism(criticism)
|
48
|
+
has_errors = false
|
49
|
+
criticism.each do |filename, file_criticism|
|
50
|
+
unless file_criticism.empty?
|
51
|
+
puts "#{filename} :\n\n"
|
52
|
+
display_file_criticism file_criticism
|
53
|
+
has_errors = true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "#{criticism.count} files checked"
|
58
|
+
has_errors
|
59
|
+
end
|
60
|
+
|
61
|
+
def display_file_criticism(criticism)
|
62
|
+
messages = Hash.new { |hash, key| hash[key] = [] }
|
63
|
+
criticism.each do |message, type|
|
40
64
|
messages[type] << message
|
41
65
|
end
|
42
66
|
|
@@ -47,6 +71,21 @@ else
|
|
47
71
|
end
|
48
72
|
puts ""
|
49
73
|
end
|
74
|
+
!criticism.empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
has_errors = if Dir.exist? opts[:path]
|
78
|
+
display_directory_criticism criticize_directory opts[:path]
|
79
|
+
else
|
80
|
+
display_file_criticism criticize_file opts[:path]
|
81
|
+
end
|
50
82
|
|
51
|
-
|
83
|
+
if has_errors
|
84
|
+
puts 'Errors found'
|
85
|
+
exit 1
|
86
|
+
else
|
87
|
+
puts 'OK'
|
88
|
+
exit 0
|
52
89
|
end
|
90
|
+
|
91
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Skeptic
|
2
|
+
module Rules
|
3
|
+
class MaxMethodArity
|
4
|
+
DESCRIPTION = 'Limit the arguments count per method'
|
5
|
+
MAX_METHOD_ARITY = 3
|
6
|
+
|
7
|
+
include SexpVisitor
|
8
|
+
|
9
|
+
def initialize(limit = nil)
|
10
|
+
@violations = []
|
11
|
+
@limit = limit || MAX_METHOD_ARITY
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply_to(code, tokens, sexp)
|
15
|
+
visit sexp
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def violations
|
20
|
+
@violations.map do |method, arity|
|
21
|
+
"#{method} has #{arity} arguments (maximum method arity: #{@limit})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def name
|
26
|
+
"Maximum method arity (#@limit)"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
on :class do |name, parents, body|
|
32
|
+
env.push :module => qualified_class_name(name)
|
33
|
+
visit body
|
34
|
+
|
35
|
+
env.pop
|
36
|
+
end
|
37
|
+
|
38
|
+
on :module do |name, body|
|
39
|
+
env.push :module => qualified_class_name(name)
|
40
|
+
visit body
|
41
|
+
|
42
|
+
env.pop
|
43
|
+
end
|
44
|
+
|
45
|
+
on :def do |name, params, _|
|
46
|
+
qualified_method_name = env[:module] + '#' + extract_name(name)
|
47
|
+
env.push :method => qualified_method_name
|
48
|
+
|
49
|
+
visit params
|
50
|
+
|
51
|
+
env.pop
|
52
|
+
end
|
53
|
+
|
54
|
+
on :defs do |target, separator, name, params, body|
|
55
|
+
method_name = extract_name(name)
|
56
|
+
class_name = extract_name(target)
|
57
|
+
class_name = env[:module] if class_name == 'self'
|
58
|
+
|
59
|
+
qualified_method_name = class_name + '.' + method_name
|
60
|
+
env.push :method => qualified_method_name
|
61
|
+
|
62
|
+
visit params
|
63
|
+
|
64
|
+
env.pop
|
65
|
+
end
|
66
|
+
|
67
|
+
on :params do |*params|
|
68
|
+
check_max_arity(params) if params
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_max_arity(params)
|
72
|
+
arguments_count = extract_param_idents(params).size
|
73
|
+
if arguments_count > @limit
|
74
|
+
@violations << [env[:method], arguments_count]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def qualified_class_name(name)
|
79
|
+
[env[:module], extract_name(name)].compact.join('::')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -6,7 +6,7 @@ module Skeptic
|
|
6
6
|
include SexpVisitor
|
7
7
|
|
8
8
|
OPERATORS_WITHOUT_SPACES_AROUND_THEM = ['**', '::', '...', '..']
|
9
|
-
IGNORED_TOKEN_TYPES = [:on_sp, :on_ignored_nl, :on_nl, :on_lparen, :on_symbeg]
|
9
|
+
IGNORED_TOKEN_TYPES = [:on_sp, :on_ignored_nl, :on_nl, :on_lparen, :on_symbeg, :on_lbracket, :on_lbrace]
|
10
10
|
|
11
11
|
def initialize(data)
|
12
12
|
@violations = []
|
@@ -94,7 +94,7 @@ module Skeptic
|
|
94
94
|
end
|
95
95
|
|
96
96
|
on :block_var do |params|
|
97
|
-
normal_params = params[1]
|
97
|
+
normal_params = params[1] || []
|
98
98
|
unless normal_params.empty?
|
99
99
|
right_param = normal_params.last
|
100
100
|
right_location = [right_param.last[0],
|
data/lib/skeptic/rules.rb
CHANGED
data/lib/skeptic/sexp_visitor.rb
CHANGED
data/lib/skeptic.rb
CHANGED
@@ -15,6 +15,7 @@ require 'skeptic/rules/english_words_for_names'
|
|
15
15
|
require 'skeptic/rules/naming_conventions'
|
16
16
|
require 'skeptic/rules/no_global_variables'
|
17
17
|
require 'skeptic/rules/spaces_around_operators'
|
18
|
+
require 'skeptic/rules/max_method_arity'
|
18
19
|
|
19
20
|
require 'skeptic/rule_table'
|
20
21
|
require 'skeptic/rules'
|
data/skeptic.gemspec
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: skeptic 0.0.
|
5
|
+
# stub: skeptic 0.0.8 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "skeptic"
|
9
|
-
s.version = "0.0.
|
9
|
+
s.version = "0.0.8"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
12
13
|
s.authors = ["Stefan Kanev"]
|
13
|
-
s.date = "
|
14
|
+
s.date = "2014-10-12"
|
14
15
|
s.description = "An experimental, half-assed, bug-ridden and highly opinionated code analyzer."
|
15
16
|
s.email = "stefan.kanev@gmail.com"
|
16
17
|
s.executables = ["skeptic"]
|
@@ -39,6 +40,7 @@ Gem::Specification.new do |s|
|
|
39
40
|
"lib/skeptic/rules/english_words_for_names.rb",
|
40
41
|
"lib/skeptic/rules/line_length.rb",
|
41
42
|
"lib/skeptic/rules/lines_per_method.rb",
|
43
|
+
"lib/skeptic/rules/max_method_arity.rb",
|
42
44
|
"lib/skeptic/rules/max_nesting_depth.rb",
|
43
45
|
"lib/skeptic/rules/methods_per_class.rb",
|
44
46
|
"lib/skeptic/rules/naming_conventions.rb",
|
@@ -52,8 +54,7 @@ Gem::Specification.new do |s|
|
|
52
54
|
]
|
53
55
|
s.homepage = "http://github.com/skanev/skeptic"
|
54
56
|
s.licenses = ["MIT"]
|
55
|
-
s.
|
56
|
-
s.rubygems_version = "2.1.5"
|
57
|
+
s.rubygems_version = "2.2.2"
|
57
58
|
s.summary = "Skeptic points out annoying things in your code"
|
58
59
|
|
59
60
|
if s.respond_to? :specification_version then
|
@@ -62,7 +63,7 @@ Gem::Specification.new do |s|
|
|
62
63
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
63
64
|
s.add_runtime_dependency(%q<trollop>, [">= 1.16.2"])
|
64
65
|
s.add_runtime_dependency(%q<ffi-aspell>, [">= 0"])
|
65
|
-
s.add_development_dependency(%q<rspec>, ["
|
66
|
+
s.add_development_dependency(%q<rspec>, ["= 2.14.1"])
|
66
67
|
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
67
68
|
s.add_development_dependency(%q<aruba>, [">= 0"])
|
68
69
|
s.add_development_dependency(%q<bundler>, [">= 0"])
|
@@ -71,7 +72,7 @@ Gem::Specification.new do |s|
|
|
71
72
|
else
|
72
73
|
s.add_dependency(%q<trollop>, [">= 1.16.2"])
|
73
74
|
s.add_dependency(%q<ffi-aspell>, [">= 0"])
|
74
|
-
s.add_dependency(%q<rspec>, ["
|
75
|
+
s.add_dependency(%q<rspec>, ["= 2.14.1"])
|
75
76
|
s.add_dependency(%q<cucumber>, [">= 0"])
|
76
77
|
s.add_dependency(%q<aruba>, [">= 0"])
|
77
78
|
s.add_dependency(%q<bundler>, [">= 0"])
|
@@ -81,7 +82,7 @@ Gem::Specification.new do |s|
|
|
81
82
|
else
|
82
83
|
s.add_dependency(%q<trollop>, [">= 1.16.2"])
|
83
84
|
s.add_dependency(%q<ffi-aspell>, [">= 0"])
|
84
|
-
s.add_dependency(%q<rspec>, ["
|
85
|
+
s.add_dependency(%q<rspec>, ["= 2.14.1"])
|
85
86
|
s.add_dependency(%q<cucumber>, [">= 0"])
|
86
87
|
s.add_dependency(%q<aruba>, [">= 0"])
|
87
88
|
s.add_dependency(%q<bundler>, [">= 0"])
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skeptic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Kanev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trollop
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 2.14.1
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 2.14.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: cucumber
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,6 +151,7 @@ files:
|
|
151
151
|
- lib/skeptic/rules/english_words_for_names.rb
|
152
152
|
- lib/skeptic/rules/line_length.rb
|
153
153
|
- lib/skeptic/rules/lines_per_method.rb
|
154
|
+
- lib/skeptic/rules/max_method_arity.rb
|
154
155
|
- lib/skeptic/rules/max_nesting_depth.rb
|
155
156
|
- lib/skeptic/rules/methods_per_class.rb
|
156
157
|
- lib/skeptic/rules/naming_conventions.rb
|
@@ -181,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
182
|
version: '0'
|
182
183
|
requirements: []
|
183
184
|
rubyforge_project:
|
184
|
-
rubygems_version: 2.
|
185
|
+
rubygems_version: 2.2.2
|
185
186
|
signing_key:
|
186
187
|
specification_version: 4
|
187
188
|
summary: Skeptic points out annoying things in your code
|