codeqa 0.3.0
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 +7 -0
- data/.codeqa.rb +22 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.rubocop.yml +93 -0
- data/.ruby-version +1 -0
- data/.travis.yml +10 -0
- data/.vimrc +1 -0
- data/CHANGELOG +8 -0
- data/Gemfile +18 -0
- data/Guardfile +21 -0
- data/LICENSE +22 -0
- data/README.md +97 -0
- data/Rakefile +19 -0
- data/bin/codeqa +75 -0
- data/codeqa.gemspec +21 -0
- data/config/default.rb +42 -0
- data/lib/codeqa/check_errors.rb +21 -0
- data/lib/codeqa/checker.rb +47 -0
- data/lib/codeqa/checkers/check_conflict.rb +28 -0
- data/lib/codeqa/checkers/check_erb.rb +48 -0
- data/lib/codeqa/checkers/check_erb_html.rb +42 -0
- data/lib/codeqa/checkers/check_linkto.rb +28 -0
- data/lib/codeqa/checkers/check_pry.rb +28 -0
- data/lib/codeqa/checkers/check_rspec_focus.rb +28 -0
- data/lib/codeqa/checkers/check_ruby_syntax.rb +25 -0
- data/lib/codeqa/checkers/check_strange_chars.rb +29 -0
- data/lib/codeqa/checkers/check_utf8_encoding.rb +22 -0
- data/lib/codeqa/checkers/check_yard.rb +55 -0
- data/lib/codeqa/checkers/pattern_checker.rb +26 -0
- data/lib/codeqa/checkers/rubocop_formatter.rb +29 -0
- data/lib/codeqa/checkers/rubocop_full.rb +53 -0
- data/lib/codeqa/checkers/rubocop_lint.rb +21 -0
- data/lib/codeqa/configuration.rb +94 -0
- data/lib/codeqa/fake_erb.rb +80 -0
- data/lib/codeqa/runner.rb +61 -0
- data/lib/codeqa/runner_decorator.rb +84 -0
- data/lib/codeqa/sourcefile.rb +50 -0
- data/lib/codeqa/version.rb +3 -0
- data/lib/codeqa.rb +78 -0
- data/lib/templates/pre-commit +50 -0
- data/spec/fixtures/html_error.html.erb +10 -0
- data/spec/fixtures/html_error.text.html +3 -0
- data/spec/fixtures/isolation/home/project/dir/.gitkeep +0 -0
- data/spec/fixtures/isolation/home/project/file.rb +1 -0
- data/spec/fixtures/isolation/home/project/ignored/some_file.txt +1 -0
- data/spec/fixtures/ruby.rb +3 -0
- data/spec/fixtures/ruby_error.rb +3 -0
- data/spec/lib/codeqa/checkers/check_conflict_spec.rb +30 -0
- data/spec/lib/codeqa/checkers/check_erb_html_spec.rb +72 -0
- data/spec/lib/codeqa/checkers/check_erb_spec.rb +31 -0
- data/spec/lib/codeqa/checkers/check_linkto_spec.rb +26 -0
- data/spec/lib/codeqa/checkers/check_pry_spec.rb +25 -0
- data/spec/lib/codeqa/checkers/check_rspec_focus_spec.rb +25 -0
- data/spec/lib/codeqa/checkers/check_ruby_syntax_spec.rb +26 -0
- data/spec/lib/codeqa/checkers/check_strange_chars_spec.rb +27 -0
- data/spec/lib/codeqa/checkers/check_utf8_encoding_spec.rb +26 -0
- data/spec/lib/codeqa/checkers/check_yard_spec.rb +21 -0
- data/spec/lib/codeqa/checkers/rubocop_formatter_spec.rb +5 -0
- data/spec/lib/codeqa/checkers/rubocop_full_spec.rb +5 -0
- data/spec/lib/codeqa/checkers/rubocop_lint_spec.rb +26 -0
- data/spec/lib/codeqa/configuration_spec.rb +52 -0
- data/spec/lib/codeqa/runner_decorator_spec.rb +19 -0
- data/spec/lib/codeqa/runner_spec.rb +5 -0
- data/spec/lib/codeqa/sourcefile_spec.rb +33 -0
- data/spec/lib/codeqa_spec.rb +52 -0
- data/spec/spec_helper.rb +56 -0
- data/spec/support/checker.rb +20 -0
- metadata +183 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'codeqa/fake_erb'
|
2
|
+
require 'open3'
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckErbHtml < Checker
|
6
|
+
def self.check?(sourcefile)
|
7
|
+
sourcefile.html?
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
'erb html'
|
12
|
+
end
|
13
|
+
|
14
|
+
def hint
|
15
|
+
'The html I see after removing the erb stuff is not valid (find the unclosed tags and attributes).'
|
16
|
+
end
|
17
|
+
|
18
|
+
def check
|
19
|
+
result = nil
|
20
|
+
with_existing_file(html) do |filename|
|
21
|
+
Open3.popen3("tidy -q -e -xml '#{filename}'") do |_in_stream, _out_stream, err_stream|
|
22
|
+
message = err_stream.read
|
23
|
+
result = message if message =~ /(Error:|missing trailing quote|end of file while parsing attributes)/m
|
24
|
+
end # IO.popen
|
25
|
+
end # Tempfile
|
26
|
+
|
27
|
+
return unless result
|
28
|
+
errors.add(nil, html)
|
29
|
+
errors.add(nil, result)
|
30
|
+
end
|
31
|
+
|
32
|
+
def html
|
33
|
+
@html ||= begin
|
34
|
+
html = FakeERB.new(sourcefile.content.gsub('<%=', '<%')).result
|
35
|
+
html = html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
|
36
|
+
html.gsub(%r{<script[ >].*?</script>|<style[ >].*?</style>}m,
|
37
|
+
'<!--removed script/style tag-->')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckLinkto < PatternChecker
|
6
|
+
def name
|
7
|
+
'link_to'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
"<% link_to ... do ... %> detected add an '=' after the <%"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.erb?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /<% link_to.* do.*%>/
|
22
|
+
end
|
23
|
+
def error_msg(_line, line_number, _pos)
|
24
|
+
"old style block link_to in line #{line_number}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckPry < PatternChecker
|
6
|
+
def name
|
7
|
+
'pry'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'Leftover binding.pry found, please remove it.'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.ruby?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /binding\.pry/
|
22
|
+
end
|
23
|
+
def error_msg(_line, line_number, _pos)
|
24
|
+
"binding.pry in line #{line_number}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckRspecFocus < PatternChecker
|
6
|
+
def name
|
7
|
+
'rspec-focus'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'Leftover :focus in spec found, please remove it.'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.spec?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /:focus/
|
22
|
+
end
|
23
|
+
def error_msg(_line, line_number, _pos)
|
24
|
+
":focus in line #{line_number}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'erb'
|
2
|
+
module Codeqa
|
3
|
+
module Checkers
|
4
|
+
class CheckRubySyntax < Checker
|
5
|
+
def self.check?(sourcefile)
|
6
|
+
sourcefile.ruby?
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
'ruby syntax'
|
11
|
+
end
|
12
|
+
|
13
|
+
def hint
|
14
|
+
'Ruby can not parse the file, please check it for syntax errors.'
|
15
|
+
end
|
16
|
+
|
17
|
+
def check
|
18
|
+
with_existing_file do |filename|
|
19
|
+
command = "/usr/bin/env ruby -c '#{filename}' 1>/dev/null 2>/dev/null"
|
20
|
+
errors.add(nil, 'Ruby syntax error') unless system(command)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckStrangeChars < PatternChecker
|
6
|
+
def name
|
7
|
+
'strange chars'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'The file contains a tab or form feed. Remove them.'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.text?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /(\x09|\x0c)/
|
22
|
+
end
|
23
|
+
def error_msg(line, line_number, pos)
|
24
|
+
strangeness = (line.include?("\x09") ? 'TAB x09' : 'FORM FEED x0C')
|
25
|
+
"#{strangeness} at line #{line_number} column #{pos + 1}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Codeqa
|
2
|
+
module Checkers
|
3
|
+
class CheckUtf8Encoding < Checker
|
4
|
+
def self.check?(sourcefile)
|
5
|
+
sourcefile.text?
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
'utf8 encoding'
|
10
|
+
end
|
11
|
+
|
12
|
+
def hint
|
13
|
+
'The file contains non utf8 characters. Find and remove them.'
|
14
|
+
end
|
15
|
+
|
16
|
+
def check
|
17
|
+
return if sourcefile.content.force_encoding('UTF-8').valid_encoding?
|
18
|
+
errors.add(nil, 'encoding error, not utf8')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckYard < Checker
|
6
|
+
def self.check?(sourcefile)
|
7
|
+
sourcefile.ruby? && !(sourcefile.filename =~ /^(test|spec)/)
|
8
|
+
end
|
9
|
+
def self.available?
|
10
|
+
yard?
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.io
|
14
|
+
@@io ||= StringIO.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
'yard'
|
19
|
+
end
|
20
|
+
|
21
|
+
def hint
|
22
|
+
'Yard gives us some warnings on the file you can run <yardoc filename> to check yourself.'
|
23
|
+
end
|
24
|
+
|
25
|
+
def check
|
26
|
+
if self.class.yard?
|
27
|
+
::YARD.parse_string(sourcefile.content) # let yard parse the file content
|
28
|
+
io.rewind # rewind the io
|
29
|
+
message = io.read
|
30
|
+
warnings = message.match(/\A\[warn\]: /)
|
31
|
+
errors.add(nil, message.gsub(/\(stdin\)/, sourcefile.filename)) if warnings
|
32
|
+
end
|
33
|
+
ensure
|
34
|
+
io.reopen # clear the message for the next file
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def io
|
40
|
+
self.class.io
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.yard?
|
44
|
+
@loaded ||= begin
|
45
|
+
require 'yard'
|
46
|
+
::YARD::Logger.instance(io) # replace YARD logger with io
|
47
|
+
true
|
48
|
+
rescue LoadError
|
49
|
+
puts 'yard not installed'
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Codeqa
|
2
|
+
module Checkers
|
3
|
+
class PatternChecker < Checker
|
4
|
+
def check
|
5
|
+
sourcefile.content.lines.each.with_index do |line, line_number|
|
6
|
+
pos = (line =~ pattern)
|
7
|
+
errors.add("#{line_number + 1},#{pos + 1}", error_msg(line, line_number + 1, pos)) if pos
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.available?
|
12
|
+
respond_to?(:pattern)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def pattern
|
18
|
+
self.class.pattern
|
19
|
+
end
|
20
|
+
|
21
|
+
def error_msg(*_args)
|
22
|
+
raise 'not implemented'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'codeqa/checkers/rubocop_full'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class RubocopFormatter < Rubocop
|
6
|
+
def name
|
7
|
+
'rubocop formatter'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
<<-EOF
|
12
|
+
Rubocop reformatted your code.
|
13
|
+
Check what it has done and add the changes to git's index
|
14
|
+
EOF
|
15
|
+
end
|
16
|
+
|
17
|
+
def after_check
|
18
|
+
# add changes to the git index
|
19
|
+
# `git add #{sourcefile.filename}`
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def config_args
|
25
|
+
%w(--auto-correct --only ) << Codeqa.configuration.rubocop_formatter_cops.to_a.join(',')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Codeqa
|
2
|
+
module Checkers
|
3
|
+
class Rubocop < Checker
|
4
|
+
def self.check?(sourcefile)
|
5
|
+
sourcefile.ruby?
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.available?
|
9
|
+
rubocop?
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
'rubocop'
|
14
|
+
end
|
15
|
+
|
16
|
+
def hint
|
17
|
+
'Rubocop does not like your syntax, please fix your code.'
|
18
|
+
end
|
19
|
+
|
20
|
+
def check
|
21
|
+
return unless self.class.rubocop?
|
22
|
+
with_existing_file do |filename|
|
23
|
+
args = config_args << filename
|
24
|
+
success, captured = capture do
|
25
|
+
if defined?(RuboCop) # its RuboCop since 0.24
|
26
|
+
::RuboCop::CLI.new.run(default_args + args) == 0
|
27
|
+
else
|
28
|
+
::Rubocop::CLI.new.run(default_args + args) == 0
|
29
|
+
end
|
30
|
+
end
|
31
|
+
errors.add(nil, captured) unless success
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def config_args
|
38
|
+
%w(--auto-correct --fail-level warning)
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_args
|
42
|
+
%w(--display-cop-names --format emacs)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.rubocop?
|
46
|
+
@loaded ||= begin
|
47
|
+
require 'rubocop'
|
48
|
+
true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'codeqa/checkers/rubocop_full'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class RubocopLint < Rubocop
|
6
|
+
def name
|
7
|
+
'rubocop lint'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'Rubocop found syntax errors, please fix your code.'
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def config_args
|
17
|
+
%w(--lint --fail-level error)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'set'
|
2
|
+
module Codeqa
|
3
|
+
class Configuration
|
4
|
+
# the default config file will setup all variables to some sane defaults
|
5
|
+
attr_accessor :erb_engine
|
6
|
+
attr_reader :excludes,
|
7
|
+
:enabled_checker,
|
8
|
+
:rubocop_formatter_cops
|
9
|
+
|
10
|
+
def excludes=(val)
|
11
|
+
@excludes = Set[*val]
|
12
|
+
end
|
13
|
+
|
14
|
+
def enabled_checker=(val)
|
15
|
+
@enabled_checker = Set[*val]
|
16
|
+
end
|
17
|
+
|
18
|
+
def rubocop_formatter_cops=(val)
|
19
|
+
@rubocop_formatter_cops = Set[*val]
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_config_path
|
23
|
+
Codeqa.root.join('config', 'default')
|
24
|
+
end
|
25
|
+
|
26
|
+
def home_config_path
|
27
|
+
home_dir_config = File.join(home_dir, DOTFILE)
|
28
|
+
return home_dir_config if File.exist? home_dir_config
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def project_config_path
|
33
|
+
project_root_config = File.join(project_root, DOTFILE)
|
34
|
+
return project_root_config if File.exist? project_root_config
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# tests a given filepath if it should be excluded
|
40
|
+
# @param file File.join compatable filepath
|
41
|
+
#
|
42
|
+
# @return [Boolean]
|
43
|
+
def excluded?(file)
|
44
|
+
file = File.join(Dir.pwd, file) unless file.start_with?('/')
|
45
|
+
Codeqa.configuration.excludes.any?{ |pattern| match_path?(pattern, file) }
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
DOTFILE = '.codeqa.rb'
|
51
|
+
|
52
|
+
def home_dir
|
53
|
+
@home_dir ||= Dir.home
|
54
|
+
end
|
55
|
+
|
56
|
+
def project_root
|
57
|
+
@project_root ||= git_root_till_home
|
58
|
+
end
|
59
|
+
|
60
|
+
# ascend from the current dir till I find a .git folder or reach home_dir
|
61
|
+
def git_root_till_home
|
62
|
+
Pathname.new(Dir.pwd).ascend do |dir_pathname|
|
63
|
+
return dir_pathname if File.directory?("#{dir_pathname}/.git")
|
64
|
+
return nil if dir_pathname.to_s == home_dir
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def match_path?(pattern, path)
|
69
|
+
case pattern
|
70
|
+
when String
|
71
|
+
basename = File.basename(path)
|
72
|
+
pattern = File.join(project_root, pattern) unless pattern.start_with?('/')
|
73
|
+
path == pattern || basename == pattern || File.fnmatch(pattern, path)
|
74
|
+
when Regexp
|
75
|
+
path =~ pattern
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class << self
|
81
|
+
def configuration
|
82
|
+
@configuration ||= Configuration.new
|
83
|
+
end
|
84
|
+
|
85
|
+
def configure
|
86
|
+
yield(configuration) if block_given?
|
87
|
+
Codeqa.register_checkers
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
require Codeqa.configuration.default_config_path
|
93
|
+
require Codeqa.configuration.home_config_path if Codeqa.configuration.home_config_path
|
94
|
+
require Codeqa.configuration.project_config_path if Codeqa.configuration.project_config_path
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'erb'
|
2
|
+
module Codeqa
|
3
|
+
# copied from ERB
|
4
|
+
# throws away all the erb stuff so only html remains
|
5
|
+
# rubocop:disable MethodLength, LineLength, CyclomaticComplexity, BlockNesting
|
6
|
+
class FakeERB < ERB
|
7
|
+
def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout', compiler_class=FakeERB::Compiler)
|
8
|
+
@safe_level = safe_level
|
9
|
+
compiler = compiler_class.new(trim_mode)
|
10
|
+
set_eoutvar(compiler, eoutvar)
|
11
|
+
@src = compiler.compile(str)
|
12
|
+
@filename = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
class Compiler < ERB::Compiler # :nodoc:
|
16
|
+
def compile(s)
|
17
|
+
out = Buffer.new(self)
|
18
|
+
|
19
|
+
content = ''
|
20
|
+
scanner = make_scanner(s)
|
21
|
+
scanner.scan do |token|
|
22
|
+
next if token.nil?
|
23
|
+
next if token == ''
|
24
|
+
if scanner.stag.nil?
|
25
|
+
case token
|
26
|
+
when PercentLine
|
27
|
+
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
|
28
|
+
content = ''
|
29
|
+
out.push(token.to_s)
|
30
|
+
out.cr
|
31
|
+
when :cr
|
32
|
+
out.cr
|
33
|
+
when '<%', '<%=', '<%#'
|
34
|
+
scanner.stag = token
|
35
|
+
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
|
36
|
+
content = ''
|
37
|
+
when "\n"
|
38
|
+
content << "\n"
|
39
|
+
out.push("#{@put_cmd} #{content_dump(content)}")
|
40
|
+
content = ''
|
41
|
+
when '<%%'
|
42
|
+
content << '<%'
|
43
|
+
else
|
44
|
+
content << token
|
45
|
+
end
|
46
|
+
else
|
47
|
+
case token
|
48
|
+
when '%>'
|
49
|
+
case scanner.stag
|
50
|
+
when '<%'
|
51
|
+
if content[-1] == "\n"
|
52
|
+
content.chop!
|
53
|
+
# out.push(content)
|
54
|
+
out.cr
|
55
|
+
else
|
56
|
+
# out.push(content)
|
57
|
+
end
|
58
|
+
when '<%='
|
59
|
+
# out.push("#{@insert_cmd}((#{content}).to_s)")
|
60
|
+
when '<%#'
|
61
|
+
# out.push("# #{content_dump(content)}")
|
62
|
+
end
|
63
|
+
scanner.stag = nil
|
64
|
+
content = ''
|
65
|
+
when '%%>'
|
66
|
+
content << '%>'
|
67
|
+
else
|
68
|
+
content << token
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# puts "pushed2 #{content}"
|
73
|
+
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
|
74
|
+
out.close
|
75
|
+
out.script
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
# rubocop:enable MethodLength, LineLength, CyclomaticComplexity, BlockNesting
|
80
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
class Runner
|
5
|
+
class << self
|
6
|
+
def registered_checkers
|
7
|
+
@@registered_checkers
|
8
|
+
end
|
9
|
+
|
10
|
+
def reset_checkers
|
11
|
+
@@registered_checkers = Set.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def register_checker(checker_class)
|
15
|
+
@@registered_checkers << checker_class
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@@registered_checkers = reset_checkers
|
19
|
+
|
20
|
+
# run the checks on source
|
21
|
+
def self.run(sourcefile)
|
22
|
+
runner = new(sourcefile)
|
23
|
+
runner.run
|
24
|
+
runner
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(sourcefile)
|
28
|
+
@sourcefile = sourcefile
|
29
|
+
@results = []
|
30
|
+
end
|
31
|
+
attr_reader :sourcefile
|
32
|
+
|
33
|
+
def run
|
34
|
+
return @results unless @results.empty?
|
35
|
+
@results = @@registered_checkers.map do |checker_klass|
|
36
|
+
next unless checker_klass.check?(sourcefile)
|
37
|
+
checker = checker_klass.new(sourcefile)
|
38
|
+
|
39
|
+
checker.before_check if checker.respond_to?(:before_check)
|
40
|
+
checker.check
|
41
|
+
checker.after_check if checker.respond_to?(:after_check)
|
42
|
+
checker
|
43
|
+
end.compact
|
44
|
+
end
|
45
|
+
|
46
|
+
# the results (checker instances of the run)
|
47
|
+
attr_reader :results
|
48
|
+
|
49
|
+
def failures
|
50
|
+
@failures ||= @results.reject{ |checker| checker.success? }
|
51
|
+
end
|
52
|
+
|
53
|
+
def success?
|
54
|
+
failures.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
def display_result(options={})
|
58
|
+
RunnerDecorator.new(self, options)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|